Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd53d408e3 | ||
|
|
ce501f14c5 | ||
|
|
b96146d014 | ||
|
|
6f18f8d375 | ||
|
|
63cf0366bd | ||
|
|
fd7ea3420f | ||
|
|
52e520be10 | ||
|
|
af718696fb | ||
|
|
2c5a00c966 | ||
|
|
3d65f9905d | ||
|
|
709366bdfe | ||
|
|
910200b637 | ||
|
|
be831d7ecb | ||
|
|
44c544160a | ||
|
|
262df0197b | ||
|
|
ed853e1ffb | ||
|
|
799554b1c5 | ||
|
|
5d0864fb41 | ||
|
|
90ffbb4170 | ||
|
|
adfd841d9d | ||
|
|
237c46512c | ||
|
|
64f999ee89 | ||
|
|
198407b5ba | ||
|
|
ab5586a7a3 | ||
|
|
79426acd55 | ||
|
|
14f579844d | ||
|
|
83495af5ce | ||
|
|
dc9c72819c | ||
|
|
1200929a72 | ||
|
|
10ab52081d | ||
|
|
fecff1bcf0 | ||
|
|
513d77788d | ||
|
|
2f5a766c71 | ||
|
|
0b9703a36f | ||
|
|
2bf6ae09b3 | ||
|
|
879750b278 | ||
|
|
04086099d0 | ||
|
|
757450b24f | ||
|
|
fbbc93906e | ||
|
|
85dbf412fd | ||
|
|
1f25f80d5b | ||
|
|
99143db529 | ||
|
|
2f99ece694 | ||
|
|
251dc3a322 | ||
|
|
c1b1e9af62 | ||
|
|
bcbbf6dacf | ||
|
|
93a924d020 | ||
|
|
6f7ac0e29c | ||
|
|
bfdfb7479d | ||
|
|
56739b8036 | ||
|
|
2c5d1036db | ||
|
|
15b0a7813d | ||
|
|
490e5ace3a | ||
|
|
6be0cf66e0 | ||
|
|
ea1a2f3fbf | ||
|
|
5ba18ec98d | ||
|
|
62b2b9bf45 | ||
|
|
244e69a10a | ||
|
|
e006ff39be | ||
|
|
9faad3da69 | ||
|
|
47a749742a | ||
|
|
9d252ff7d2 | ||
|
|
9b4213bb3f | ||
|
|
0cc7fd3498 | ||
|
|
1638a98f0e | ||
|
|
85cc06f56c | ||
|
|
76054b4646 | ||
|
|
9b95c00218 | ||
|
|
b8186ff707 | ||
|
|
f5538049ef | ||
|
|
119d9ad3aa | ||
|
|
8b0910d31f | ||
|
|
cd48f2d313 | ||
|
|
26f98a5e56 | ||
|
|
bbfc7b1ea2 | ||
|
|
1e3fa455c9 | ||
|
|
d00198bd14 | ||
|
|
ff4b11441b | ||
|
|
904733362e | ||
|
|
44de3dd8da | ||
|
|
ceb75ca9ff | ||
|
|
55edd253ff | ||
|
|
2ae10f0b33 | ||
|
|
b9cc513f2f | ||
|
|
14192d21dd | ||
|
|
19719bf57f | ||
|
|
ea8cb9b7bb | ||
|
|
72ac20b7d7 | ||
|
|
7b4e946f74 | ||
|
|
85397cf893 | ||
|
|
d10ba45b4b | ||
|
|
ce7746b49e | ||
|
|
354e08673b | ||
|
|
c552943f9e | ||
|
|
810395f913 | ||
|
|
8dfdec39fd | ||
|
|
0abecbc87d | ||
|
|
efbb62b5bd | ||
|
|
24f5b98e8c | ||
|
|
dd5e309d31 | ||
|
|
0c0b1e1498 | ||
|
|
0d54bf3711 | ||
|
|
920aa8280f | ||
|
|
8a2c820213 | ||
|
|
ab08379d1c | ||
|
|
321cd769b7 | ||
|
|
802974ec84 | ||
|
|
91cb892574 | ||
|
|
4703c1399d | ||
|
|
e58e9e1fb9 | ||
|
|
5894e1b085 | ||
|
|
dc25a1a62b | ||
|
|
754b233873 | ||
|
|
5617ad7c18 | ||
|
|
909f1a1a30 | ||
|
|
f6837a8ef4 | ||
|
|
d287c6c8b0 | ||
|
|
488735e4a2 | ||
|
|
43d597b30f | ||
|
|
a3f676461c | ||
|
|
607667f89d | ||
|
|
6212b342f6 | ||
|
|
5ddb691286 | ||
|
|
6f905e1f0f | ||
|
|
4ccedfaec4 | ||
|
|
c010901ea9 | ||
|
|
c0bedd810f | ||
|
|
5d66bf5a1f | ||
|
|
d4b614d655 | ||
|
|
f55296bdf0 | ||
|
|
bed000d72e | ||
|
|
b2181df698 | ||
|
|
6469ae095f | ||
|
|
636e904b09 | ||
|
|
2c343f8ac1 | ||
|
|
da85dcc288 | ||
|
|
07050778e3 | ||
|
|
ac3cb936ee | ||
|
|
d183e03dc3 | ||
|
|
41646a2294 | ||
|
|
2a1688c8f5 | ||
|
|
6ba062e067 | ||
|
|
089381e2b1 | ||
|
|
ef3d739cdf | ||
|
|
0f7d84bbbf | ||
|
|
94253c0df4 | ||
|
|
30c48b68df | ||
|
|
7088b7efe3 | ||
|
|
13ccdabc07 | ||
|
|
203bbab7c9 | ||
|
|
93d3ea1393 | ||
|
|
462ffc7927 | ||
|
|
a13289725c | ||
|
|
a638162ed4 | ||
|
|
c77bd091df | ||
|
|
8fb5bb0f20 | ||
|
|
6db42b86e6 | ||
|
|
8066c6a687 | ||
|
|
4671050f10 | ||
|
|
fca34fb8d0 | ||
|
|
0e31751aed | ||
|
|
d5c18c780a | ||
|
|
19e0981d35 | ||
|
|
b2a59d29b6 | ||
|
|
d917353c7e | ||
|
|
5fdbd4a749 | ||
|
|
b3800e2fed | ||
|
|
67b6b8b92c | ||
|
|
17cf9db2f7 | ||
|
|
e7e8174dba | ||
|
|
4b357897d5 | ||
|
|
68275b03de | ||
|
|
2645c0ef3a | ||
|
|
7de961e9fa | ||
|
|
c26df8ae12 | ||
|
|
d1c1cbf476 | ||
|
|
4166996b42 | ||
|
|
47692f4e99 | ||
|
|
649902f7fa | ||
|
|
e7e764dbdf | ||
|
|
b0aa1e2416 | ||
|
|
3cd704802f | ||
|
|
ea1cc886b5 | ||
|
|
3dba96d22a | ||
|
|
a0ea496ffb | ||
|
|
1ef8141062 | ||
|
|
893b999f51 | ||
|
|
1a7f4b5e4c | ||
|
|
2d2102400e | ||
|
|
e1dcac30d8 | ||
|
|
ad6dcfad67 | ||
|
|
cc89e55f7d | ||
|
|
3703dbd940 | ||
|
|
8da19e064b | ||
|
|
666afa7352 | ||
|
|
5e02396d5e | ||
|
|
2e108cd831 | ||
|
|
27fb8875b7 | ||
|
|
cdb6b73776 | ||
|
|
fad7a0e23d | ||
|
|
da7cc28446 | ||
|
|
e6e391530f | ||
|
|
a0256cda63 | ||
|
|
85daeb5e16 |
@@ -0,0 +1,14 @@
|
||||
compat/zlib/contrib/dotzlib/DotZLib/UnitTests.cs
|
||||
compat/zlib/contrib/vstudio/readme.txt
|
||||
compat/zlib/contrib/vstudio/*/zlib.rc
|
||||
compat/zlib/win32/*.txt
|
||||
compat/zlib/win64/*.txt
|
||||
tools/tcl.hpj.in
|
||||
tools/tcl.wse.in
|
||||
win/buildall.vc.bat
|
||||
win/coffbase.txt
|
||||
win/makefile.vc
|
||||
win/rules.vc
|
||||
win/tcl.dsp
|
||||
win/tcl.dsw
|
||||
win/tcl.hpj.in
|
||||
@@ -7,7 +7,6 @@ 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
|
||||
|
||||
@@ -2,7 +2,6 @@ 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
|
||||
|
||||
@@ -3,7 +3,7 @@ set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
|
||||
|
||||
project(zlib C)
|
||||
|
||||
set(VERSION "1.2.10")
|
||||
set(VERSION "1.2.11")
|
||||
|
||||
option(ASM686 "Enable building i686 assembly implementation")
|
||||
option(AMD64 "Enable building amd64 assembly implementation")
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
|
||||
ChangeLog file for zlib
|
||||
|
||||
Changes in 1.2.11 (15 Jan 2017)
|
||||
- Fix deflate stored bug when pulling last block from window
|
||||
- Permit immediate deflateParams changes before any deflate input
|
||||
|
||||
Changes in 1.2.10 (2 Jan 2017)
|
||||
- Avoid warnings on snprintf() return value
|
||||
- Fix bug in deflate_stored() for zero-length input
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Makefile for zlib
|
||||
# Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
|
||||
# Copyright (C) 1995-2017 Jean-loup Gailly, Mark Adler
|
||||
# For conditions of distribution and use, see copyright notice in zlib.h
|
||||
|
||||
# To compile and test, type:
|
||||
@@ -32,7 +32,7 @@ CPP=$(CC) -E
|
||||
|
||||
STATICLIB=libz.a
|
||||
SHAREDLIB=libz.so
|
||||
SHAREDLIBV=libz.so.1.2.10
|
||||
SHAREDLIBV=libz.so.1.2.11
|
||||
SHAREDLIBM=libz.so.1
|
||||
LIBS=$(STATICLIB) $(SHAREDLIBV)
|
||||
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
ZLIB DATA COMPRESSION LIBRARY
|
||||
|
||||
zlib 1.2.10 is a general purpose data compression library. All the code is
|
||||
zlib 1.2.11 is a general purpose data compression library. All the code is
|
||||
thread safe. The data format used by the zlib library is described by RFCs
|
||||
(Request for Comments) 1950 to 1952 in the files
|
||||
http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and
|
||||
@@ -31,7 +31,7 @@ Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
|
||||
issue of Dr. Dobb's Journal; a copy of the article is available at
|
||||
http://marknelson.us/1997/01/01/zlib-engine/ .
|
||||
|
||||
The changes made in version 1.2.10 are documented in the file ChangeLog.
|
||||
The changes made in version 1.2.11 are documented in the file ChangeLog.
|
||||
|
||||
Unsupported third party contributions are provided in directory contrib/ .
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer;
|
||||
const OutBuf: Pointer; BufSize: Integer);
|
||||
|
||||
const
|
||||
zlib_version = '1.2.10';
|
||||
zlib_version = '1.2.11';
|
||||
|
||||
type
|
||||
EZlibError = class(Exception);
|
||||
|
||||
@@ -156,7 +156,7 @@ namespace DotZLibTests
|
||||
public void Info_Version()
|
||||
{
|
||||
Info info = new Info();
|
||||
Assert.AreEqual("1.2.10", Info.Version);
|
||||
Assert.AreEqual("1.2.11", Info.Version);
|
||||
Assert.AreEqual(32, info.SizeOfUInt);
|
||||
Assert.AreEqual(32, info.SizeOfULong);
|
||||
Assert.AreEqual(32, info.SizeOfPointer);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#define MAXBITS 15
|
||||
|
||||
const char inflate9_copyright[] =
|
||||
" inflate9 1.2.10 Copyright 1995-2017 Mark Adler ";
|
||||
" inflate9 1.2.11 Copyright 1995-2017 Mark Adler ";
|
||||
/*
|
||||
If you use the zlib library in a product, an acknowledgment is welcome
|
||||
in the documentation of your product. If for some reason you cannot
|
||||
@@ -64,7 +64,7 @@ unsigned short FAR *work;
|
||||
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
|
||||
128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129,
|
||||
130, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132,
|
||||
133, 133, 133, 133, 144, 192, 202};
|
||||
133, 133, 133, 133, 144, 77, 202};
|
||||
static const unsigned short dbase[32] = { /* Distance codes 0..31 base */
|
||||
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49,
|
||||
65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# -*- Autoconf -*-
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_INIT([minizip], [1.2.10], [bugzilla.redhat.com])
|
||||
AC_INIT([minizip], [1.2.11], [bugzilla.redhat.com])
|
||||
AC_CONFIG_SRCDIR([minizip.c])
|
||||
AM_INIT_AUTOMAKE([foreign])
|
||||
LT_INIT
|
||||
|
||||
@@ -10,7 +10,7 @@ unit zlibpas;
|
||||
interface
|
||||
|
||||
const
|
||||
ZLIB_VERSION = '1.2.10';
|
||||
ZLIB_VERSION = '1.2.11';
|
||||
ZLIB_VERNUM = $12a0;
|
||||
|
||||
type
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Building instructions for the DLL versions of Zlib 1.2.10
|
||||
Building instructions for the DLL versions of Zlib 1.2.11
|
||||
========================================================
|
||||
|
||||
This directory contains projects that build zlib and minizip using
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
#define IDR_VERSION1 1
|
||||
IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
|
||||
FILEVERSION 1, 2, 10, 0
|
||||
PRODUCTVERSION 1, 2, 10, 0
|
||||
FILEVERSION 1, 2, 11, 0
|
||||
PRODUCTVERSION 1, 2, 11, 0
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
FILEFLAGS 0
|
||||
FILEOS VOS_DOS_WINDOWS32
|
||||
@@ -17,7 +17,7 @@ BEGIN
|
||||
|
||||
BEGIN
|
||||
VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
|
||||
VALUE "FileVersion", "1.2.10\0"
|
||||
VALUE "FileVersion", "1.2.11\0"
|
||||
VALUE "InternalName", "zlib\0"
|
||||
VALUE "OriginalFilename", "zlibwapi.dll\0"
|
||||
VALUE "ProductName", "ZLib.DLL\0"
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
#define IDR_VERSION1 1
|
||||
IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
|
||||
FILEVERSION 1, 2, 10, 0
|
||||
PRODUCTVERSION 1, 2, 10, 0
|
||||
FILEVERSION 1, 2, 11, 0
|
||||
PRODUCTVERSION 1, 2, 11, 0
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
FILEFLAGS 0
|
||||
FILEOS VOS_DOS_WINDOWS32
|
||||
@@ -17,7 +17,7 @@ BEGIN
|
||||
|
||||
BEGIN
|
||||
VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
|
||||
VALUE "FileVersion", "1.2.10\0"
|
||||
VALUE "FileVersion", "1.2.11\0"
|
||||
VALUE "InternalName", "zlib\0"
|
||||
VALUE "OriginalFilename", "zlibwapi.dll\0"
|
||||
VALUE "ProductName", "ZLib.DLL\0"
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
#define IDR_VERSION1 1
|
||||
IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
|
||||
FILEVERSION 1, 2, 10, 0
|
||||
PRODUCTVERSION 1, 2, 10, 0
|
||||
FILEVERSION 1, 2, 11, 0
|
||||
PRODUCTVERSION 1, 2, 11, 0
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
FILEFLAGS 0
|
||||
FILEOS VOS_DOS_WINDOWS32
|
||||
@@ -17,7 +17,7 @@ BEGIN
|
||||
|
||||
BEGIN
|
||||
VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
|
||||
VALUE "FileVersion", "1.2.10\0"
|
||||
VALUE "FileVersion", "1.2.11\0"
|
||||
VALUE "InternalName", "zlib\0"
|
||||
VALUE "OriginalFilename", "zlibwapi.dll\0"
|
||||
VALUE "ProductName", "ZLib.DLL\0"
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
#define IDR_VERSION1 1
|
||||
IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
|
||||
FILEVERSION 1, 2, 10, 0
|
||||
PRODUCTVERSION 1, 2, 10, 0
|
||||
FILEVERSION 1, 2, 11, 0
|
||||
PRODUCTVERSION 1, 2, 11, 0
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
FILEFLAGS 0
|
||||
FILEOS VOS_DOS_WINDOWS32
|
||||
@@ -17,7 +17,7 @@ BEGIN
|
||||
|
||||
BEGIN
|
||||
VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
|
||||
VALUE "FileVersion", "1.2.10\0"
|
||||
VALUE "FileVersion", "1.2.11\0"
|
||||
VALUE "InternalName", "zlib\0"
|
||||
VALUE "OriginalFilename", "zlibwapi.dll\0"
|
||||
VALUE "ProductName", "ZLib.DLL\0"
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
#define IDR_VERSION1 1
|
||||
IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
|
||||
FILEVERSION 1, 2, 10, 0
|
||||
PRODUCTVERSION 1, 2, 10, 0
|
||||
FILEVERSION 1, 2, 11, 0
|
||||
PRODUCTVERSION 1, 2, 11, 0
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
FILEFLAGS 0
|
||||
FILEOS VOS_DOS_WINDOWS32
|
||||
@@ -17,7 +17,7 @@ BEGIN
|
||||
|
||||
BEGIN
|
||||
VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
|
||||
VALUE "FileVersion", "1.2.10\0"
|
||||
VALUE "FileVersion", "1.2.11\0"
|
||||
VALUE "InternalName", "zlib\0"
|
||||
VALUE "OriginalFilename", "zlibwapi.dll\0"
|
||||
VALUE "ProductName", "ZLib.DLL\0"
|
||||
|
||||
+12
-7
@@ -52,7 +52,7 @@
|
||||
#include "deflate.h"
|
||||
|
||||
const char deflate_copyright[] =
|
||||
" deflate 1.2.10 Copyright 1995-2017 Jean-loup Gailly and Mark Adler ";
|
||||
" deflate 1.2.11 Copyright 1995-2017 Jean-loup Gailly and Mark Adler ";
|
||||
/*
|
||||
If you use the zlib library in a product, an acknowledgment is welcome
|
||||
in the documentation of your product. If for some reason you cannot
|
||||
@@ -586,7 +586,8 @@ int ZEXPORT deflateParams(strm, level, strategy)
|
||||
}
|
||||
func = configuration_table[s->level].func;
|
||||
|
||||
if ((strategy != s->strategy || func != configuration_table[level].func)) {
|
||||
if ((strategy != s->strategy || func != configuration_table[level].func) &&
|
||||
s->high_water) {
|
||||
/* Flush the last buffer: */
|
||||
int err = deflate(strm, Z_BLOCK);
|
||||
if (err == Z_STREAM_ERROR)
|
||||
@@ -1671,8 +1672,6 @@ local block_state deflate_stored(s, flush)
|
||||
len = left + s->strm->avail_in; /* limit len to the input */
|
||||
if (len > have)
|
||||
len = have; /* limit len to the output */
|
||||
if (left > len)
|
||||
left = len; /* limit window pull to len */
|
||||
|
||||
/* If the stored block would be less than min_block in length, or if
|
||||
* unable to copy all of the available input when flushing, then try
|
||||
@@ -1681,13 +1680,13 @@ local block_state deflate_stored(s, flush)
|
||||
*/
|
||||
if (len < min_block && ((len == 0 && flush != Z_FINISH) ||
|
||||
flush == Z_NO_FLUSH ||
|
||||
len - left != s->strm->avail_in))
|
||||
len != left + s->strm->avail_in))
|
||||
break;
|
||||
|
||||
/* Make a dummy stored block in pending to get the header bytes,
|
||||
* including any pending bits. This also updates the debugging counts.
|
||||
*/
|
||||
last = flush == Z_FINISH && len - left == s->strm->avail_in ? 1 : 0;
|
||||
last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0;
|
||||
_tr_stored_block(s, (char *)0, 0L, last);
|
||||
|
||||
/* Replace the lengths in the dummy stored block with len. */
|
||||
@@ -1699,14 +1698,16 @@ local block_state deflate_stored(s, flush)
|
||||
/* Write the stored block header bytes. */
|
||||
flush_pending(s->strm);
|
||||
|
||||
/* Update debugging counts for the data about to be copied. */
|
||||
#ifdef ZLIB_DEBUG
|
||||
/* Update debugging counts for the data about to be copied. */
|
||||
s->compressed_len += len << 3;
|
||||
s->bits_sent += len << 3;
|
||||
#endif
|
||||
|
||||
/* Copy uncompressed bytes from the window to next_out. */
|
||||
if (left) {
|
||||
if (left > len)
|
||||
left = len;
|
||||
zmemcpy(s->strm->next_out, s->window + s->block_start, left);
|
||||
s->strm->next_out += left;
|
||||
s->strm->avail_out -= left;
|
||||
@@ -1756,6 +1757,8 @@ local block_state deflate_stored(s, flush)
|
||||
s->block_start = s->strstart;
|
||||
s->insert += MIN(used, s->w_size - s->insert);
|
||||
}
|
||||
if (s->high_water < s->strstart)
|
||||
s->high_water = s->strstart;
|
||||
|
||||
/* If the last block was written to next_out, then done. */
|
||||
if (last)
|
||||
@@ -1783,6 +1786,8 @@ local block_state deflate_stored(s, flush)
|
||||
read_buf(s->strm, s->window + s->strstart, have);
|
||||
s->strstart += have;
|
||||
}
|
||||
if (s->high_water < s->strstart)
|
||||
s->high_water = s->strstart;
|
||||
|
||||
/* There was not enough avail_out to write a complete worthy or flushed
|
||||
* stored block to next_out. Write a stored block to pending instead, if we
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
1. Compression algorithm (deflate)
|
||||
|
||||
The deflation algorithm used by gzip (also zip and zlib) is a variation of
|
||||
LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in
|
||||
the input data. The second occurrence of a string is replaced by a
|
||||
pointer to the previous string, in the form of a pair (distance,
|
||||
length). Distances are limited to 32K bytes, and lengths are limited
|
||||
to 258 bytes. When a string does not occur anywhere in the previous
|
||||
32K bytes, it is emitted as a sequence of literal bytes. (In this
|
||||
description, `string' must be taken as an arbitrary sequence of bytes,
|
||||
and is not restricted to printable characters.)
|
||||
|
||||
Literals or match lengths are compressed with one Huffman tree, and
|
||||
match distances are compressed with another tree. The trees are stored
|
||||
in a compact form at the start of each block. The blocks can have any
|
||||
size (except that the compressed data for one block must fit in
|
||||
available memory). A block is terminated when deflate() determines that
|
||||
it would be useful to start another block with fresh trees. (This is
|
||||
somewhat similar to the behavior of LZW-based _compress_.)
|
||||
|
||||
Duplicated strings are found using a hash table. All input strings of
|
||||
length 3 are inserted in the hash table. A hash index is computed for
|
||||
the next 3 bytes. If the hash chain for this index is not empty, all
|
||||
strings in the chain are compared with the current input string, and
|
||||
the longest match is selected.
|
||||
|
||||
The hash chains are searched starting with the most recent strings, to
|
||||
favor small distances and thus take advantage of the Huffman encoding.
|
||||
The hash chains are singly linked. There are no deletions from the
|
||||
hash chains, the algorithm simply discards matches that are too old.
|
||||
|
||||
To avoid a worst-case situation, very long hash chains are arbitrarily
|
||||
truncated at a certain length, determined by a runtime option (level
|
||||
parameter of deflateInit). So deflate() does not always find the longest
|
||||
possible match but generally finds a match which is long enough.
|
||||
|
||||
deflate() also defers the selection of matches with a lazy evaluation
|
||||
mechanism. After a match of length N has been found, deflate() searches for
|
||||
a longer match at the next input byte. If a longer match is found, the
|
||||
previous match is truncated to a length of one (thus producing a single
|
||||
literal byte) and the process of lazy evaluation begins again. Otherwise,
|
||||
the original match is kept, and the next match search is attempted only N
|
||||
steps later.
|
||||
|
||||
The lazy match evaluation is also subject to a runtime parameter. If
|
||||
the current match is long enough, deflate() reduces the search for a longer
|
||||
match, thus speeding up the whole process. If compression ratio is more
|
||||
important than speed, deflate() attempts a complete second search even if
|
||||
the first match is already long enough.
|
||||
|
||||
The lazy match evaluation is not performed for the fastest compression
|
||||
modes (level parameter 1 to 3). For these fast modes, new strings
|
||||
are inserted in the hash table only when no match was found, or
|
||||
when the match is not too long. This degrades the compression ratio
|
||||
but saves time since there are both fewer insertions and fewer searches.
|
||||
|
||||
|
||||
2. Decompression algorithm (inflate)
|
||||
|
||||
2.1 Introduction
|
||||
|
||||
The key question is how to represent a Huffman code (or any prefix code) so
|
||||
that you can decode fast. The most important characteristic is that shorter
|
||||
codes are much more common than longer codes, so pay attention to decoding the
|
||||
short codes fast, and let the long codes take longer to decode.
|
||||
|
||||
inflate() sets up a first level table that covers some number of bits of
|
||||
input less than the length of longest code. It gets that many bits from the
|
||||
stream, and looks it up in the table. The table will tell if the next
|
||||
code is that many bits or less and how many, and if it is, it will tell
|
||||
the value, else it will point to the next level table for which inflate()
|
||||
grabs more bits and tries to decode a longer code.
|
||||
|
||||
How many bits to make the first lookup is a tradeoff between the time it
|
||||
takes to decode and the time it takes to build the table. If building the
|
||||
table took no time (and if you had infinite memory), then there would only
|
||||
be a first level table to cover all the way to the longest code. However,
|
||||
building the table ends up taking a lot longer for more bits since short
|
||||
codes are replicated many times in such a table. What inflate() does is
|
||||
simply to make the number of bits in the first table a variable, and then
|
||||
to set that variable for the maximum speed.
|
||||
|
||||
For inflate, which has 286 possible codes for the literal/length tree, the size
|
||||
of the first table is nine bits. Also the distance trees have 30 possible
|
||||
values, and the size of the first table is six bits. Note that for each of
|
||||
those cases, the table ended up one bit longer than the ``average'' code
|
||||
length, i.e. the code length of an approximately flat code which would be a
|
||||
little more than eight bits for 286 symbols and a little less than five bits
|
||||
for 30 symbols.
|
||||
|
||||
|
||||
2.2 More details on the inflate table lookup
|
||||
|
||||
Ok, you want to know what this cleverly obfuscated inflate tree actually
|
||||
looks like. You are correct that it's not a Huffman tree. It is simply a
|
||||
lookup table for the first, let's say, nine bits of a Huffman symbol. The
|
||||
symbol could be as short as one bit or as long as 15 bits. If a particular
|
||||
symbol is shorter than nine bits, then that symbol's translation is duplicated
|
||||
in all those entries that start with that symbol's bits. For example, if the
|
||||
symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a
|
||||
symbol is nine bits long, it appears in the table once.
|
||||
|
||||
If the symbol is longer than nine bits, then that entry in the table points
|
||||
to another similar table for the remaining bits. Again, there are duplicated
|
||||
entries as needed. The idea is that most of the time the symbol will be short
|
||||
and there will only be one table look up. (That's whole idea behind data
|
||||
compression in the first place.) For the less frequent long symbols, there
|
||||
will be two lookups. If you had a compression method with really long
|
||||
symbols, you could have as many levels of lookups as is efficient. For
|
||||
inflate, two is enough.
|
||||
|
||||
So a table entry either points to another table (in which case nine bits in
|
||||
the above example are gobbled), or it contains the translation for the symbol
|
||||
and the number of bits to gobble. Then you start again with the next
|
||||
ungobbled bit.
|
||||
|
||||
You may wonder: why not just have one lookup table for how ever many bits the
|
||||
longest symbol is? The reason is that if you do that, you end up spending
|
||||
more time filling in duplicate symbol entries than you do actually decoding.
|
||||
At least for deflate's output that generates new trees every several 10's of
|
||||
kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code
|
||||
would take too long if you're only decoding several thousand symbols. At the
|
||||
other extreme, you could make a new table for every bit in the code. In fact,
|
||||
that's essentially a Huffman tree. But then you spend too much time
|
||||
traversing the tree while decoding, even for short symbols.
|
||||
|
||||
So the number of bits for the first lookup table is a trade of the time to
|
||||
fill out the table vs. the time spent looking at the second level and above of
|
||||
the table.
|
||||
|
||||
Here is an example, scaled down:
|
||||
|
||||
The code being decoded, with 10 symbols, from 1 to 6 bits long:
|
||||
|
||||
A: 0
|
||||
B: 10
|
||||
C: 1100
|
||||
D: 11010
|
||||
E: 11011
|
||||
F: 11100
|
||||
G: 11101
|
||||
H: 11110
|
||||
I: 111110
|
||||
J: 111111
|
||||
|
||||
Let's make the first table three bits long (eight entries):
|
||||
|
||||
000: A,1
|
||||
001: A,1
|
||||
010: A,1
|
||||
011: A,1
|
||||
100: B,2
|
||||
101: B,2
|
||||
110: -> table X (gobble 3 bits)
|
||||
111: -> table Y (gobble 3 bits)
|
||||
|
||||
Each entry is what the bits decode as and how many bits that is, i.e. how
|
||||
many bits to gobble. Or the entry points to another table, with the number of
|
||||
bits to gobble implicit in the size of the table.
|
||||
|
||||
Table X is two bits long since the longest code starting with 110 is five bits
|
||||
long:
|
||||
|
||||
00: C,1
|
||||
01: C,1
|
||||
10: D,2
|
||||
11: E,2
|
||||
|
||||
Table Y is three bits long since the longest code starting with 111 is six
|
||||
bits long:
|
||||
|
||||
000: F,2
|
||||
001: F,2
|
||||
010: G,2
|
||||
011: G,2
|
||||
100: H,2
|
||||
101: H,2
|
||||
110: I,3
|
||||
111: J,3
|
||||
|
||||
So what we have here are three tables with a total of 20 entries that had to
|
||||
be constructed. That's compared to 64 entries for a single table. Or
|
||||
compared to 16 entries for a Huffman tree (six two entry tables and one four
|
||||
entry table). Assuming that the code ideally represents the probability of
|
||||
the symbols, it takes on the average 1.25 lookups per symbol. That's compared
|
||||
to one lookup for the single table, or 1.66 lookups per symbol for the
|
||||
Huffman tree.
|
||||
|
||||
There, I think that gives you a picture of what's going on. For inflate, the
|
||||
meaning of a particular symbol is often more than just a letter. It can be a
|
||||
byte (a "literal"), or it can be either a length or a distance which
|
||||
indicates a base value and a number of bits to fetch after the code that is
|
||||
added to the base value. Or it might be the special end-of-block code. The
|
||||
data structures created in inftrees.c try to encode all that information
|
||||
compactly in the tables.
|
||||
|
||||
|
||||
Jean-loup Gailly Mark Adler
|
||||
jloup@gzip.org madler@alumni.caltech.edu
|
||||
|
||||
|
||||
References:
|
||||
|
||||
[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data
|
||||
Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3,
|
||||
pp. 337-343.
|
||||
|
||||
``DEFLATE Compressed Data Format Specification'' available in
|
||||
http://tools.ietf.org/html/rfc1951
|
||||
@@ -1,619 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Network Working Group P. Deutsch
|
||||
Request for Comments: 1950 Aladdin Enterprises
|
||||
Category: Informational J-L. Gailly
|
||||
Info-ZIP
|
||||
May 1996
|
||||
|
||||
|
||||
ZLIB Compressed Data Format Specification version 3.3
|
||||
|
||||
Status of This Memo
|
||||
|
||||
This memo provides information for the Internet community. This memo
|
||||
does not specify an Internet standard of any kind. Distribution of
|
||||
this memo is unlimited.
|
||||
|
||||
IESG Note:
|
||||
|
||||
The IESG takes no position on the validity of any Intellectual
|
||||
Property Rights statements contained in this document.
|
||||
|
||||
Notices
|
||||
|
||||
Copyright (c) 1996 L. Peter Deutsch and Jean-Loup Gailly
|
||||
|
||||
Permission is granted to copy and distribute this document for any
|
||||
purpose and without charge, including translations into other
|
||||
languages and incorporation into compilations, provided that the
|
||||
copyright notice and this notice are preserved, and that any
|
||||
substantive changes or deletions from the original are clearly
|
||||
marked.
|
||||
|
||||
A pointer to the latest version of this and related documentation in
|
||||
HTML format can be found at the URL
|
||||
<ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html>.
|
||||
|
||||
Abstract
|
||||
|
||||
This specification defines a lossless compressed data format. The
|
||||
data can be produced or consumed, even for an arbitrarily long
|
||||
sequentially presented input data stream, using only an a priori
|
||||
bounded amount of intermediate storage. The format presently uses
|
||||
the DEFLATE compression method but can be easily extended to use
|
||||
other compression methods. It can be implemented readily in a manner
|
||||
not covered by patents. This specification also defines the ADLER-32
|
||||
checksum (an extension and improvement of the Fletcher checksum),
|
||||
used for detection of data corruption, and provides an algorithm for
|
||||
computing it.
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch & Gailly Informational [Page 1]
|
||||
|
||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
Table of Contents
|
||||
|
||||
1. Introduction ................................................... 2
|
||||
1.1. Purpose ................................................... 2
|
||||
1.2. Intended audience ......................................... 3
|
||||
1.3. Scope ..................................................... 3
|
||||
1.4. Compliance ................................................ 3
|
||||
1.5. Definitions of terms and conventions used ................ 3
|
||||
1.6. Changes from previous versions ............................ 3
|
||||
2. Detailed specification ......................................... 3
|
||||
2.1. Overall conventions ....................................... 3
|
||||
2.2. Data format ............................................... 4
|
||||
2.3. Compliance ................................................ 7
|
||||
3. References ..................................................... 7
|
||||
4. Source code .................................................... 8
|
||||
5. Security Considerations ........................................ 8
|
||||
6. Acknowledgements ............................................... 8
|
||||
7. Authors' Addresses ............................................. 8
|
||||
8. Appendix: Rationale ............................................ 9
|
||||
9. Appendix: Sample code ..........................................10
|
||||
|
||||
1. Introduction
|
||||
|
||||
1.1. Purpose
|
||||
|
||||
The purpose of this specification is to define a lossless
|
||||
compressed data format that:
|
||||
|
||||
* Is independent of CPU type, operating system, file system,
|
||||
and character set, and hence can be used for interchange;
|
||||
|
||||
* Can be produced or consumed, even for an arbitrarily long
|
||||
sequentially presented input data stream, using only an a
|
||||
priori bounded amount of intermediate storage, and hence can
|
||||
be used in data communications or similar structures such as
|
||||
Unix filters;
|
||||
|
||||
* Can use a number of different compression methods;
|
||||
|
||||
* Can be implemented readily in a manner not covered by
|
||||
patents, and hence can be practiced freely.
|
||||
|
||||
The data format defined by this specification does not attempt to
|
||||
allow random access to compressed data.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch & Gailly Informational [Page 2]
|
||||
|
||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
1.2. Intended audience
|
||||
|
||||
This specification is intended for use by implementors of software
|
||||
to compress data into zlib format and/or decompress data from zlib
|
||||
format.
|
||||
|
||||
The text of the specification assumes a basic background in
|
||||
programming at the level of bits and other primitive data
|
||||
representations.
|
||||
|
||||
1.3. Scope
|
||||
|
||||
The specification specifies a compressed data format that can be
|
||||
used for in-memory compression of a sequence of arbitrary bytes.
|
||||
|
||||
1.4. Compliance
|
||||
|
||||
Unless otherwise indicated below, a compliant decompressor must be
|
||||
able to accept and decompress any data set that conforms to all
|
||||
the specifications presented here; a compliant compressor must
|
||||
produce data sets that conform to all the specifications presented
|
||||
here.
|
||||
|
||||
1.5. Definitions of terms and conventions used
|
||||
|
||||
byte: 8 bits stored or transmitted as a unit (same as an octet).
|
||||
(For this specification, a byte is exactly 8 bits, even on
|
||||
machines which store a character on a number of bits different
|
||||
from 8.) See below, for the numbering of bits within a byte.
|
||||
|
||||
1.6. Changes from previous versions
|
||||
|
||||
Version 3.1 was the first public release of this specification.
|
||||
In version 3.2, some terminology was changed and the Adler-32
|
||||
sample code was rewritten for clarity. In version 3.3, the
|
||||
support for a preset dictionary was introduced, and the
|
||||
specification was converted to RFC style.
|
||||
|
||||
2. Detailed specification
|
||||
|
||||
2.1. Overall conventions
|
||||
|
||||
In the diagrams below, a box like this:
|
||||
|
||||
+---+
|
||||
| | <-- the vertical bars might be missing
|
||||
+---+
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch & Gailly Informational [Page 3]
|
||||
|
||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
represents one byte; a box like this:
|
||||
|
||||
+==============+
|
||||
| |
|
||||
+==============+
|
||||
|
||||
represents a variable number of bytes.
|
||||
|
||||
Bytes stored within a computer do not have a "bit order", since
|
||||
they are always treated as a unit. However, a byte considered as
|
||||
an integer between 0 and 255 does have a most- and least-
|
||||
significant bit, and since we write numbers with the most-
|
||||
significant digit on the left, we also write bytes with the most-
|
||||
significant bit on the left. In the diagrams below, we number the
|
||||
bits of a byte so that bit 0 is the least-significant bit, i.e.,
|
||||
the bits are numbered:
|
||||
|
||||
+--------+
|
||||
|76543210|
|
||||
+--------+
|
||||
|
||||
Within a computer, a number may occupy multiple bytes. All
|
||||
multi-byte numbers in the format described here are stored with
|
||||
the MOST-significant byte first (at the lower memory address).
|
||||
For example, the decimal number 520 is stored as:
|
||||
|
||||
0 1
|
||||
+--------+--------+
|
||||
|00000010|00001000|
|
||||
+--------+--------+
|
||||
^ ^
|
||||
| |
|
||||
| + less significant byte = 8
|
||||
+ more significant byte = 2 x 256
|
||||
|
||||
2.2. Data format
|
||||
|
||||
A zlib stream has the following structure:
|
||||
|
||||
0 1
|
||||
+---+---+
|
||||
|CMF|FLG| (more-->)
|
||||
+---+---+
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch & Gailly Informational [Page 4]
|
||||
|
||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
(if FLG.FDICT set)
|
||||
|
||||
0 1 2 3
|
||||
+---+---+---+---+
|
||||
| DICTID | (more-->)
|
||||
+---+---+---+---+
|
||||
|
||||
+=====================+---+---+---+---+
|
||||
|...compressed data...| ADLER32 |
|
||||
+=====================+---+---+---+---+
|
||||
|
||||
Any data which may appear after ADLER32 are not part of the zlib
|
||||
stream.
|
||||
|
||||
CMF (Compression Method and flags)
|
||||
This byte is divided into a 4-bit compression method and a 4-
|
||||
bit information field depending on the compression method.
|
||||
|
||||
bits 0 to 3 CM Compression method
|
||||
bits 4 to 7 CINFO Compression info
|
||||
|
||||
CM (Compression method)
|
||||
This identifies the compression method used in the file. CM = 8
|
||||
denotes the "deflate" compression method with a window size up
|
||||
to 32K. This is the method used by gzip and PNG (see
|
||||
references [1] and [2] in Chapter 3, below, for the reference
|
||||
documents). CM = 15 is reserved. It might be used in a future
|
||||
version of this specification to indicate the presence of an
|
||||
extra field before the compressed data.
|
||||
|
||||
CINFO (Compression info)
|
||||
For CM = 8, CINFO is the base-2 logarithm of the LZ77 window
|
||||
size, minus eight (CINFO=7 indicates a 32K window size). Values
|
||||
of CINFO above 7 are not allowed in this version of the
|
||||
specification. CINFO is not defined in this specification for
|
||||
CM not equal to 8.
|
||||
|
||||
FLG (FLaGs)
|
||||
This flag byte is divided as follows:
|
||||
|
||||
bits 0 to 4 FCHECK (check bits for CMF and FLG)
|
||||
bit 5 FDICT (preset dictionary)
|
||||
bits 6 to 7 FLEVEL (compression level)
|
||||
|
||||
The FCHECK value must be such that CMF and FLG, when viewed as
|
||||
a 16-bit unsigned integer stored in MSB order (CMF*256 + FLG),
|
||||
is a multiple of 31.
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch & Gailly Informational [Page 5]
|
||||
|
||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
FDICT (Preset dictionary)
|
||||
If FDICT is set, a DICT dictionary identifier is present
|
||||
immediately after the FLG byte. The dictionary is a sequence of
|
||||
bytes which are initially fed to the compressor without
|
||||
producing any compressed output. DICT is the Adler-32 checksum
|
||||
of this sequence of bytes (see the definition of ADLER32
|
||||
below). The decompressor can use this identifier to determine
|
||||
which dictionary has been used by the compressor.
|
||||
|
||||
FLEVEL (Compression level)
|
||||
These flags are available for use by specific compression
|
||||
methods. The "deflate" method (CM = 8) sets these flags as
|
||||
follows:
|
||||
|
||||
0 - compressor used fastest algorithm
|
||||
1 - compressor used fast algorithm
|
||||
2 - compressor used default algorithm
|
||||
3 - compressor used maximum compression, slowest algorithm
|
||||
|
||||
The information in FLEVEL is not needed for decompression; it
|
||||
is there to indicate if recompression might be worthwhile.
|
||||
|
||||
compressed data
|
||||
For compression method 8, the compressed data is stored in the
|
||||
deflate compressed data format as described in the document
|
||||
"DEFLATE Compressed Data Format Specification" by L. Peter
|
||||
Deutsch. (See reference [3] in Chapter 3, below)
|
||||
|
||||
Other compressed data formats are not specified in this version
|
||||
of the zlib specification.
|
||||
|
||||
ADLER32 (Adler-32 checksum)
|
||||
This contains a checksum value of the uncompressed data
|
||||
(excluding any dictionary data) computed according to Adler-32
|
||||
algorithm. This algorithm is a 32-bit extension and improvement
|
||||
of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073
|
||||
standard. See references [4] and [5] in Chapter 3, below)
|
||||
|
||||
Adler-32 is composed of two sums accumulated per byte: s1 is
|
||||
the sum of all bytes, s2 is the sum of all s1 values. Both sums
|
||||
are done modulo 65521. s1 is initialized to 1, s2 to zero. The
|
||||
Adler-32 checksum is stored as s2*65536 + s1 in most-
|
||||
significant-byte first (network) order.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch & Gailly Informational [Page 6]
|
||||
|
||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
2.3. Compliance
|
||||
|
||||
A compliant compressor must produce streams with correct CMF, FLG
|
||||
and ADLER32, but need not support preset dictionaries. When the
|
||||
zlib data format is used as part of another standard data format,
|
||||
the compressor may use only preset dictionaries that are specified
|
||||
by this other data format. If this other format does not use the
|
||||
preset dictionary feature, the compressor must not set the FDICT
|
||||
flag.
|
||||
|
||||
A compliant decompressor must check CMF, FLG, and ADLER32, and
|
||||
provide an error indication if any of these have incorrect values.
|
||||
A compliant decompressor must give an error indication if CM is
|
||||
not one of the values defined in this specification (only the
|
||||
value 8 is permitted in this version), since another value could
|
||||
indicate the presence of new features that would cause subsequent
|
||||
data to be interpreted incorrectly. A compliant decompressor must
|
||||
give an error indication if FDICT is set and DICTID is not the
|
||||
identifier of a known preset dictionary. A decompressor may
|
||||
ignore FLEVEL and still be compliant. When the zlib data format
|
||||
is being used as a part of another standard format, a compliant
|
||||
decompressor must support all the preset dictionaries specified by
|
||||
the other format. When the other format does not use the preset
|
||||
dictionary feature, a compliant decompressor must reject any
|
||||
stream in which the FDICT flag is set.
|
||||
|
||||
3. References
|
||||
|
||||
[1] Deutsch, L.P.,"GZIP Compressed Data Format Specification",
|
||||
available in ftp://ftp.uu.net/pub/archiving/zip/doc/
|
||||
|
||||
[2] Thomas Boutell, "PNG (Portable Network Graphics) specification",
|
||||
available in ftp://ftp.uu.net/graphics/png/documents/
|
||||
|
||||
[3] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification",
|
||||
available in ftp://ftp.uu.net/pub/archiving/zip/doc/
|
||||
|
||||
[4] Fletcher, J. G., "An Arithmetic Checksum for Serial
|
||||
Transmissions," IEEE Transactions on Communications, Vol. COM-30,
|
||||
No. 1, January 1982, pp. 247-252.
|
||||
|
||||
[5] ITU-T Recommendation X.224, Annex D, "Checksum Algorithms,"
|
||||
November, 1993, pp. 144, 145. (Available from
|
||||
gopher://info.itu.ch). ITU-T X.244 is also the same as ISO 8073.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch & Gailly Informational [Page 7]
|
||||
|
||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
4. Source code
|
||||
|
||||
Source code for a C language implementation of a "zlib" compliant
|
||||
library is available at ftp://ftp.uu.net/pub/archiving/zip/zlib/.
|
||||
|
||||
5. Security Considerations
|
||||
|
||||
A decoder that fails to check the ADLER32 checksum value may be
|
||||
subject to undetected data corruption.
|
||||
|
||||
6. Acknowledgements
|
||||
|
||||
Trademarks cited in this document are the property of their
|
||||
respective owners.
|
||||
|
||||
Jean-Loup Gailly and Mark Adler designed the zlib format and wrote
|
||||
the related software described in this specification. Glenn
|
||||
Randers-Pehrson converted this document to RFC and HTML format.
|
||||
|
||||
7. Authors' Addresses
|
||||
|
||||
L. Peter Deutsch
|
||||
Aladdin Enterprises
|
||||
203 Santa Margarita Ave.
|
||||
Menlo Park, CA 94025
|
||||
|
||||
Phone: (415) 322-0103 (AM only)
|
||||
FAX: (415) 322-1734
|
||||
EMail: <ghost@aladdin.com>
|
||||
|
||||
|
||||
Jean-Loup Gailly
|
||||
|
||||
EMail: <gzip@prep.ai.mit.edu>
|
||||
|
||||
Questions about the technical content of this specification can be
|
||||
sent by email to
|
||||
|
||||
Jean-Loup Gailly <gzip@prep.ai.mit.edu> and
|
||||
Mark Adler <madler@alumni.caltech.edu>
|
||||
|
||||
Editorial comments on this specification can be sent by email to
|
||||
|
||||
L. Peter Deutsch <ghost@aladdin.com> and
|
||||
Glenn Randers-Pehrson <randeg@alumni.rpi.edu>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch & Gailly Informational [Page 8]
|
||||
|
||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
8. Appendix: Rationale
|
||||
|
||||
8.1. Preset dictionaries
|
||||
|
||||
A preset dictionary is specially useful to compress short input
|
||||
sequences. The compressor can take advantage of the dictionary
|
||||
context to encode the input in a more compact manner. The
|
||||
decompressor can be initialized with the appropriate context by
|
||||
virtually decompressing a compressed version of the dictionary
|
||||
without producing any output. However for certain compression
|
||||
algorithms such as the deflate algorithm this operation can be
|
||||
achieved without actually performing any decompression.
|
||||
|
||||
The compressor and the decompressor must use exactly the same
|
||||
dictionary. The dictionary may be fixed or may be chosen among a
|
||||
certain number of predefined dictionaries, according to the kind
|
||||
of input data. The decompressor can determine which dictionary has
|
||||
been chosen by the compressor by checking the dictionary
|
||||
identifier. This document does not specify the contents of
|
||||
predefined dictionaries, since the optimal dictionaries are
|
||||
application specific. Standard data formats using this feature of
|
||||
the zlib specification must precisely define the allowed
|
||||
dictionaries.
|
||||
|
||||
8.2. The Adler-32 algorithm
|
||||
|
||||
The Adler-32 algorithm is much faster than the CRC32 algorithm yet
|
||||
still provides an extremely low probability of undetected errors.
|
||||
|
||||
The modulo on unsigned long accumulators can be delayed for 5552
|
||||
bytes, so the modulo operation time is negligible. If the bytes
|
||||
are a, b, c, the second sum is 3a + 2b + c + 3, and so is position
|
||||
and order sensitive, unlike the first sum, which is just a
|
||||
checksum. That 65521 is prime is important to avoid a possible
|
||||
large class of two-byte errors that leave the check unchanged.
|
||||
(The Fletcher checksum uses 255, which is not prime and which also
|
||||
makes the Fletcher check insensitive to single byte changes 0 <->
|
||||
255.)
|
||||
|
||||
The sum s1 is initialized to 1 instead of zero to make the length
|
||||
of the sequence part of s2, so that the length does not have to be
|
||||
checked separately. (Any sequence of zeroes has a Fletcher
|
||||
checksum of zero.)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch & Gailly Informational [Page 9]
|
||||
|
||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
9. Appendix: Sample code
|
||||
|
||||
The following C code computes the Adler-32 checksum of a data buffer.
|
||||
It is written for clarity, not for speed. The sample code is in the
|
||||
ANSI C programming language. Non C users may find it easier to read
|
||||
with these hints:
|
||||
|
||||
& Bitwise AND operator.
|
||||
>> Bitwise right shift operator. When applied to an
|
||||
unsigned quantity, as here, right shift inserts zero bit(s)
|
||||
at the left.
|
||||
<< Bitwise left shift operator. Left shift inserts zero
|
||||
bit(s) at the right.
|
||||
++ "n++" increments the variable n.
|
||||
% modulo operator: a % b is the remainder of a divided by b.
|
||||
|
||||
#define BASE 65521 /* largest prime smaller than 65536 */
|
||||
|
||||
/*
|
||||
Update a running Adler-32 checksum with the bytes buf[0..len-1]
|
||||
and return the updated checksum. The Adler-32 checksum should be
|
||||
initialized to 1.
|
||||
|
||||
Usage example:
|
||||
|
||||
unsigned long adler = 1L;
|
||||
|
||||
while (read_buffer(buffer, length) != EOF) {
|
||||
adler = update_adler32(adler, buffer, length);
|
||||
}
|
||||
if (adler != original_adler) error();
|
||||
*/
|
||||
unsigned long update_adler32(unsigned long adler,
|
||||
unsigned char *buf, int len)
|
||||
{
|
||||
unsigned long s1 = adler & 0xffff;
|
||||
unsigned long s2 = (adler >> 16) & 0xffff;
|
||||
int n;
|
||||
|
||||
for (n = 0; n < len; n++) {
|
||||
s1 = (s1 + buf[n]) % BASE;
|
||||
s2 = (s2 + s1) % BASE;
|
||||
}
|
||||
return (s2 << 16) + s1;
|
||||
}
|
||||
|
||||
/* Return the adler32 of the bytes buf[0..len-1] */
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch & Gailly Informational [Page 10]
|
||||
|
||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
unsigned long adler32(unsigned char *buf, int len)
|
||||
{
|
||||
return update_adler32(1L, buf, len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch & Gailly Informational [Page 11]
|
||||
|
||||
@@ -1,955 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Network Working Group P. Deutsch
|
||||
Request for Comments: 1951 Aladdin Enterprises
|
||||
Category: Informational May 1996
|
||||
|
||||
|
||||
DEFLATE Compressed Data Format Specification version 1.3
|
||||
|
||||
Status of This Memo
|
||||
|
||||
This memo provides information for the Internet community. This memo
|
||||
does not specify an Internet standard of any kind. Distribution of
|
||||
this memo is unlimited.
|
||||
|
||||
IESG Note:
|
||||
|
||||
The IESG takes no position on the validity of any Intellectual
|
||||
Property Rights statements contained in this document.
|
||||
|
||||
Notices
|
||||
|
||||
Copyright (c) 1996 L. Peter Deutsch
|
||||
|
||||
Permission is granted to copy and distribute this document for any
|
||||
purpose and without charge, including translations into other
|
||||
languages and incorporation into compilations, provided that the
|
||||
copyright notice and this notice are preserved, and that any
|
||||
substantive changes or deletions from the original are clearly
|
||||
marked.
|
||||
|
||||
A pointer to the latest version of this and related documentation in
|
||||
HTML format can be found at the URL
|
||||
<ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html>.
|
||||
|
||||
Abstract
|
||||
|
||||
This specification defines a lossless compressed data format that
|
||||
compresses data using a combination of the LZ77 algorithm and Huffman
|
||||
coding, with efficiency comparable to the best currently available
|
||||
general-purpose compression methods. The data can be produced or
|
||||
consumed, even for an arbitrarily long sequentially presented input
|
||||
data stream, using only an a priori bounded amount of intermediate
|
||||
storage. The format can be implemented readily in a manner not
|
||||
covered by patents.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 1]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
Table of Contents
|
||||
|
||||
1. Introduction ................................................... 2
|
||||
1.1. Purpose ................................................... 2
|
||||
1.2. Intended audience ......................................... 3
|
||||
1.3. Scope ..................................................... 3
|
||||
1.4. Compliance ................................................ 3
|
||||
1.5. Definitions of terms and conventions used ................ 3
|
||||
1.6. Changes from previous versions ............................ 4
|
||||
2. Compressed representation overview ............................. 4
|
||||
3. Detailed specification ......................................... 5
|
||||
3.1. Overall conventions ....................................... 5
|
||||
3.1.1. Packing into bytes .................................. 5
|
||||
3.2. Compressed block format ................................... 6
|
||||
3.2.1. Synopsis of prefix and Huffman coding ............... 6
|
||||
3.2.2. Use of Huffman coding in the "deflate" format ....... 7
|
||||
3.2.3. Details of block format ............................. 9
|
||||
3.2.4. Non-compressed blocks (BTYPE=00) ................... 11
|
||||
3.2.5. Compressed blocks (length and distance codes) ...... 11
|
||||
3.2.6. Compression with fixed Huffman codes (BTYPE=01) .... 12
|
||||
3.2.7. Compression with dynamic Huffman codes (BTYPE=10) .. 13
|
||||
3.3. Compliance ............................................... 14
|
||||
4. Compression algorithm details ................................. 14
|
||||
5. References .................................................... 16
|
||||
6. Security Considerations ....................................... 16
|
||||
7. Source code ................................................... 16
|
||||
8. Acknowledgements .............................................. 16
|
||||
9. Author's Address .............................................. 17
|
||||
|
||||
1. Introduction
|
||||
|
||||
1.1. Purpose
|
||||
|
||||
The purpose of this specification is to define a lossless
|
||||
compressed data format that:
|
||||
* Is independent of CPU type, operating system, file system,
|
||||
and character set, and hence can be used for interchange;
|
||||
* Can be produced or consumed, even for an arbitrarily long
|
||||
sequentially presented input data stream, using only an a
|
||||
priori bounded amount of intermediate storage, and hence
|
||||
can be used in data communications or similar structures
|
||||
such as Unix filters;
|
||||
* Compresses data with efficiency comparable to the best
|
||||
currently available general-purpose compression methods,
|
||||
and in particular considerably better than the "compress"
|
||||
program;
|
||||
* Can be implemented readily in a manner not covered by
|
||||
patents, and hence can be practiced freely;
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 2]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
* Is compatible with the file format produced by the current
|
||||
widely used gzip utility, in that conforming decompressors
|
||||
will be able to read data produced by the existing gzip
|
||||
compressor.
|
||||
|
||||
The data format defined by this specification does not attempt to:
|
||||
|
||||
* Allow random access to compressed data;
|
||||
* Compress specialized data (e.g., raster graphics) as well
|
||||
as the best currently available specialized algorithms.
|
||||
|
||||
A simple counting argument shows that no lossless compression
|
||||
algorithm can compress every possible input data set. For the
|
||||
format defined here, the worst case expansion is 5 bytes per 32K-
|
||||
byte block, i.e., a size increase of 0.015% for large data sets.
|
||||
English text usually compresses by a factor of 2.5 to 3;
|
||||
executable files usually compress somewhat less; graphical data
|
||||
such as raster images may compress much more.
|
||||
|
||||
1.2. Intended audience
|
||||
|
||||
This specification is intended for use by implementors of software
|
||||
to compress data into "deflate" format and/or decompress data from
|
||||
"deflate" format.
|
||||
|
||||
The text of the specification assumes a basic background in
|
||||
programming at the level of bits and other primitive data
|
||||
representations. Familiarity with the technique of Huffman coding
|
||||
is helpful but not required.
|
||||
|
||||
1.3. Scope
|
||||
|
||||
The specification specifies a method for representing a sequence
|
||||
of bytes as a (usually shorter) sequence of bits, and a method for
|
||||
packing the latter bit sequence into bytes.
|
||||
|
||||
1.4. Compliance
|
||||
|
||||
Unless otherwise indicated below, a compliant decompressor must be
|
||||
able to accept and decompress any data set that conforms to all
|
||||
the specifications presented here; a compliant compressor must
|
||||
produce data sets that conform to all the specifications presented
|
||||
here.
|
||||
|
||||
1.5. Definitions of terms and conventions used
|
||||
|
||||
Byte: 8 bits stored or transmitted as a unit (same as an octet).
|
||||
For this specification, a byte is exactly 8 bits, even on machines
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 3]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
which store a character on a number of bits different from eight.
|
||||
See below, for the numbering of bits within a byte.
|
||||
|
||||
String: a sequence of arbitrary bytes.
|
||||
|
||||
1.6. Changes from previous versions
|
||||
|
||||
There have been no technical changes to the deflate format since
|
||||
version 1.1 of this specification. In version 1.2, some
|
||||
terminology was changed. Version 1.3 is a conversion of the
|
||||
specification to RFC style.
|
||||
|
||||
2. Compressed representation overview
|
||||
|
||||
A compressed data set consists of a series of blocks, corresponding
|
||||
to successive blocks of input data. The block sizes are arbitrary,
|
||||
except that non-compressible blocks are limited to 65,535 bytes.
|
||||
|
||||
Each block is compressed using a combination of the LZ77 algorithm
|
||||
and Huffman coding. The Huffman trees for each block are independent
|
||||
of those for previous or subsequent blocks; the LZ77 algorithm may
|
||||
use a reference to a duplicated string occurring in a previous block,
|
||||
up to 32K input bytes before.
|
||||
|
||||
Each block consists of two parts: a pair of Huffman code trees that
|
||||
describe the representation of the compressed data part, and a
|
||||
compressed data part. (The Huffman trees themselves are compressed
|
||||
using Huffman encoding.) The compressed data consists of a series of
|
||||
elements of two types: literal bytes (of strings that have not been
|
||||
detected as duplicated within the previous 32K input bytes), and
|
||||
pointers to duplicated strings, where a pointer is represented as a
|
||||
pair <length, backward distance>. The representation used in the
|
||||
"deflate" format limits distances to 32K bytes and lengths to 258
|
||||
bytes, but does not limit the size of a block, except for
|
||||
uncompressible blocks, which are limited as noted above.
|
||||
|
||||
Each type of value (literals, distances, and lengths) in the
|
||||
compressed data is represented using a Huffman code, using one code
|
||||
tree for literals and lengths and a separate code tree for distances.
|
||||
The code trees for each block appear in a compact form just before
|
||||
the compressed data for that block.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 4]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
3. Detailed specification
|
||||
|
||||
3.1. Overall conventions In the diagrams below, a box like this:
|
||||
|
||||
+---+
|
||||
| | <-- the vertical bars might be missing
|
||||
+---+
|
||||
|
||||
represents one byte; a box like this:
|
||||
|
||||
+==============+
|
||||
| |
|
||||
+==============+
|
||||
|
||||
represents a variable number of bytes.
|
||||
|
||||
Bytes stored within a computer do not have a "bit order", since
|
||||
they are always treated as a unit. However, a byte considered as
|
||||
an integer between 0 and 255 does have a most- and least-
|
||||
significant bit, and since we write numbers with the most-
|
||||
significant digit on the left, we also write bytes with the most-
|
||||
significant bit on the left. In the diagrams below, we number the
|
||||
bits of a byte so that bit 0 is the least-significant bit, i.e.,
|
||||
the bits are numbered:
|
||||
|
||||
+--------+
|
||||
|76543210|
|
||||
+--------+
|
||||
|
||||
Within a computer, a number may occupy multiple bytes. All
|
||||
multi-byte numbers in the format described here are stored with
|
||||
the least-significant byte first (at the lower memory address).
|
||||
For example, the decimal number 520 is stored as:
|
||||
|
||||
0 1
|
||||
+--------+--------+
|
||||
|00001000|00000010|
|
||||
+--------+--------+
|
||||
^ ^
|
||||
| |
|
||||
| + more significant byte = 2 x 256
|
||||
+ less significant byte = 8
|
||||
|
||||
3.1.1. Packing into bytes
|
||||
|
||||
This document does not address the issue of the order in which
|
||||
bits of a byte are transmitted on a bit-sequential medium,
|
||||
since the final data format described here is byte- rather than
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 5]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
bit-oriented. However, we describe the compressed block format
|
||||
in below, as a sequence of data elements of various bit
|
||||
lengths, not a sequence of bytes. We must therefore specify
|
||||
how to pack these data elements into bytes to form the final
|
||||
compressed byte sequence:
|
||||
|
||||
* Data elements are packed into bytes in order of
|
||||
increasing bit number within the byte, i.e., starting
|
||||
with the least-significant bit of the byte.
|
||||
* Data elements other than Huffman codes are packed
|
||||
starting with the least-significant bit of the data
|
||||
element.
|
||||
* Huffman codes are packed starting with the most-
|
||||
significant bit of the code.
|
||||
|
||||
In other words, if one were to print out the compressed data as
|
||||
a sequence of bytes, starting with the first byte at the
|
||||
*right* margin and proceeding to the *left*, with the most-
|
||||
significant bit of each byte on the left as usual, one would be
|
||||
able to parse the result from right to left, with fixed-width
|
||||
elements in the correct MSB-to-LSB order and Huffman codes in
|
||||
bit-reversed order (i.e., with the first bit of the code in the
|
||||
relative LSB position).
|
||||
|
||||
3.2. Compressed block format
|
||||
|
||||
3.2.1. Synopsis of prefix and Huffman coding
|
||||
|
||||
Prefix coding represents symbols from an a priori known
|
||||
alphabet by bit sequences (codes), one code for each symbol, in
|
||||
a manner such that different symbols may be represented by bit
|
||||
sequences of different lengths, but a parser can always parse
|
||||
an encoded string unambiguously symbol-by-symbol.
|
||||
|
||||
We define a prefix code in terms of a binary tree in which the
|
||||
two edges descending from each non-leaf node are labeled 0 and
|
||||
1 and in which the leaf nodes correspond one-for-one with (are
|
||||
labeled with) the symbols of the alphabet; then the code for a
|
||||
symbol is the sequence of 0's and 1's on the edges leading from
|
||||
the root to the leaf labeled with that symbol. For example:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 6]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
/\ Symbol Code
|
||||
0 1 ------ ----
|
||||
/ \ A 00
|
||||
/\ B B 1
|
||||
0 1 C 011
|
||||
/ \ D 010
|
||||
A /\
|
||||
0 1
|
||||
/ \
|
||||
D C
|
||||
|
||||
A parser can decode the next symbol from an encoded input
|
||||
stream by walking down the tree from the root, at each step
|
||||
choosing the edge corresponding to the next input bit.
|
||||
|
||||
Given an alphabet with known symbol frequencies, the Huffman
|
||||
algorithm allows the construction of an optimal prefix code
|
||||
(one which represents strings with those symbol frequencies
|
||||
using the fewest bits of any possible prefix codes for that
|
||||
alphabet). Such a code is called a Huffman code. (See
|
||||
reference [1] in Chapter 5, references for additional
|
||||
information on Huffman codes.)
|
||||
|
||||
Note that in the "deflate" format, the Huffman codes for the
|
||||
various alphabets must not exceed certain maximum code lengths.
|
||||
This constraint complicates the algorithm for computing code
|
||||
lengths from symbol frequencies. Again, see Chapter 5,
|
||||
references for details.
|
||||
|
||||
3.2.2. Use of Huffman coding in the "deflate" format
|
||||
|
||||
The Huffman codes used for each alphabet in the "deflate"
|
||||
format have two additional rules:
|
||||
|
||||
* All codes of a given bit length have lexicographically
|
||||
consecutive values, in the same order as the symbols
|
||||
they represent;
|
||||
|
||||
* Shorter codes lexicographically precede longer codes.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 7]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
We could recode the example above to follow this rule as
|
||||
follows, assuming that the order of the alphabet is ABCD:
|
||||
|
||||
Symbol Code
|
||||
------ ----
|
||||
A 10
|
||||
B 0
|
||||
C 110
|
||||
D 111
|
||||
|
||||
I.e., 0 precedes 10 which precedes 11x, and 110 and 111 are
|
||||
lexicographically consecutive.
|
||||
|
||||
Given this rule, we can define the Huffman code for an alphabet
|
||||
just by giving the bit lengths of the codes for each symbol of
|
||||
the alphabet in order; this is sufficient to determine the
|
||||
actual codes. In our example, the code is completely defined
|
||||
by the sequence of bit lengths (2, 1, 3, 3). The following
|
||||
algorithm generates the codes as integers, intended to be read
|
||||
from most- to least-significant bit. The code lengths are
|
||||
initially in tree[I].Len; the codes are produced in
|
||||
tree[I].Code.
|
||||
|
||||
1) Count the number of codes for each code length. Let
|
||||
bl_count[N] be the number of codes of length N, N >= 1.
|
||||
|
||||
2) Find the numerical value of the smallest code for each
|
||||
code length:
|
||||
|
||||
code = 0;
|
||||
bl_count[0] = 0;
|
||||
for (bits = 1; bits <= MAX_BITS; bits++) {
|
||||
code = (code + bl_count[bits-1]) << 1;
|
||||
next_code[bits] = code;
|
||||
}
|
||||
|
||||
3) Assign numerical values to all codes, using consecutive
|
||||
values for all codes of the same length with the base
|
||||
values determined at step 2. Codes that are never used
|
||||
(which have a bit length of zero) must not be assigned a
|
||||
value.
|
||||
|
||||
for (n = 0; n <= max_code; n++) {
|
||||
len = tree[n].Len;
|
||||
if (len != 0) {
|
||||
tree[n].Code = next_code[len];
|
||||
next_code[len]++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 8]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
}
|
||||
|
||||
Example:
|
||||
|
||||
Consider the alphabet ABCDEFGH, with bit lengths (3, 3, 3, 3,
|
||||
3, 2, 4, 4). After step 1, we have:
|
||||
|
||||
N bl_count[N]
|
||||
- -----------
|
||||
2 1
|
||||
3 5
|
||||
4 2
|
||||
|
||||
Step 2 computes the following next_code values:
|
||||
|
||||
N next_code[N]
|
||||
- ------------
|
||||
1 0
|
||||
2 0
|
||||
3 2
|
||||
4 14
|
||||
|
||||
Step 3 produces the following code values:
|
||||
|
||||
Symbol Length Code
|
||||
------ ------ ----
|
||||
A 3 010
|
||||
B 3 011
|
||||
C 3 100
|
||||
D 3 101
|
||||
E 3 110
|
||||
F 2 00
|
||||
G 4 1110
|
||||
H 4 1111
|
||||
|
||||
3.2.3. Details of block format
|
||||
|
||||
Each block of compressed data begins with 3 header bits
|
||||
containing the following data:
|
||||
|
||||
first bit BFINAL
|
||||
next 2 bits BTYPE
|
||||
|
||||
Note that the header bits do not necessarily begin on a byte
|
||||
boundary, since a block does not necessarily occupy an integral
|
||||
number of bytes.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 9]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
BFINAL is set if and only if this is the last block of the data
|
||||
set.
|
||||
|
||||
BTYPE specifies how the data are compressed, as follows:
|
||||
|
||||
00 - no compression
|
||||
01 - compressed with fixed Huffman codes
|
||||
10 - compressed with dynamic Huffman codes
|
||||
11 - reserved (error)
|
||||
|
||||
The only difference between the two compressed cases is how the
|
||||
Huffman codes for the literal/length and distance alphabets are
|
||||
defined.
|
||||
|
||||
In all cases, the decoding algorithm for the actual data is as
|
||||
follows:
|
||||
|
||||
do
|
||||
read block header from input stream.
|
||||
if stored with no compression
|
||||
skip any remaining bits in current partially
|
||||
processed byte
|
||||
read LEN and NLEN (see next section)
|
||||
copy LEN bytes of data to output
|
||||
otherwise
|
||||
if compressed with dynamic Huffman codes
|
||||
read representation of code trees (see
|
||||
subsection below)
|
||||
loop (until end of block code recognized)
|
||||
decode literal/length value from input stream
|
||||
if value < 256
|
||||
copy value (literal byte) to output stream
|
||||
otherwise
|
||||
if value = end of block (256)
|
||||
break from loop
|
||||
otherwise (value = 257..285)
|
||||
decode distance from input stream
|
||||
|
||||
move backwards distance bytes in the output
|
||||
stream, and copy length bytes from this
|
||||
position to the output stream.
|
||||
end loop
|
||||
while not last block
|
||||
|
||||
Note that a duplicated string reference may refer to a string
|
||||
in a previous block; i.e., the backward distance may cross one
|
||||
or more block boundaries. However a distance cannot refer past
|
||||
the beginning of the output stream. (An application using a
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 10]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
preset dictionary might discard part of the output stream; a
|
||||
distance can refer to that part of the output stream anyway)
|
||||
Note also that the referenced string may overlap the current
|
||||
position; for example, if the last 2 bytes decoded have values
|
||||
X and Y, a string reference with <length = 5, distance = 2>
|
||||
adds X,Y,X,Y,X to the output stream.
|
||||
|
||||
We now specify each compression method in turn.
|
||||
|
||||
3.2.4. Non-compressed blocks (BTYPE=00)
|
||||
|
||||
Any bits of input up to the next byte boundary are ignored.
|
||||
The rest of the block consists of the following information:
|
||||
|
||||
0 1 2 3 4...
|
||||
+---+---+---+---+================================+
|
||||
| LEN | NLEN |... LEN bytes of literal data...|
|
||||
+---+---+---+---+================================+
|
||||
|
||||
LEN is the number of data bytes in the block. NLEN is the
|
||||
one's complement of LEN.
|
||||
|
||||
3.2.5. Compressed blocks (length and distance codes)
|
||||
|
||||
As noted above, encoded data blocks in the "deflate" format
|
||||
consist of sequences of symbols drawn from three conceptually
|
||||
distinct alphabets: either literal bytes, from the alphabet of
|
||||
byte values (0..255), or <length, backward distance> pairs,
|
||||
where the length is drawn from (3..258) and the distance is
|
||||
drawn from (1..32,768). In fact, the literal and length
|
||||
alphabets are merged into a single alphabet (0..285), where
|
||||
values 0..255 represent literal bytes, the value 256 indicates
|
||||
end-of-block, and values 257..285 represent length codes
|
||||
(possibly in conjunction with extra bits following the symbol
|
||||
code) as follows:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 11]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
Extra Extra Extra
|
||||
Code Bits Length(s) Code Bits Lengths Code Bits Length(s)
|
||||
---- ---- ------ ---- ---- ------- ---- ---- -------
|
||||
257 0 3 267 1 15,16 277 4 67-82
|
||||
258 0 4 268 1 17,18 278 4 83-98
|
||||
259 0 5 269 2 19-22 279 4 99-114
|
||||
260 0 6 270 2 23-26 280 4 115-130
|
||||
261 0 7 271 2 27-30 281 5 131-162
|
||||
262 0 8 272 2 31-34 282 5 163-194
|
||||
263 0 9 273 3 35-42 283 5 195-226
|
||||
264 0 10 274 3 43-50 284 5 227-257
|
||||
265 1 11,12 275 3 51-58 285 0 258
|
||||
266 1 13,14 276 3 59-66
|
||||
|
||||
The extra bits should be interpreted as a machine integer
|
||||
stored with the most-significant bit first, e.g., bits 1110
|
||||
represent the value 14.
|
||||
|
||||
Extra Extra Extra
|
||||
Code Bits Dist Code Bits Dist Code Bits Distance
|
||||
---- ---- ---- ---- ---- ------ ---- ---- --------
|
||||
0 0 1 10 4 33-48 20 9 1025-1536
|
||||
1 0 2 11 4 49-64 21 9 1537-2048
|
||||
2 0 3 12 5 65-96 22 10 2049-3072
|
||||
3 0 4 13 5 97-128 23 10 3073-4096
|
||||
4 1 5,6 14 6 129-192 24 11 4097-6144
|
||||
5 1 7,8 15 6 193-256 25 11 6145-8192
|
||||
6 2 9-12 16 7 257-384 26 12 8193-12288
|
||||
7 2 13-16 17 7 385-512 27 12 12289-16384
|
||||
8 3 17-24 18 8 513-768 28 13 16385-24576
|
||||
9 3 25-32 19 8 769-1024 29 13 24577-32768
|
||||
|
||||
3.2.6. Compression with fixed Huffman codes (BTYPE=01)
|
||||
|
||||
The Huffman codes for the two alphabets are fixed, and are not
|
||||
represented explicitly in the data. The Huffman code lengths
|
||||
for the literal/length alphabet are:
|
||||
|
||||
Lit Value Bits Codes
|
||||
--------- ---- -----
|
||||
0 - 143 8 00110000 through
|
||||
10111111
|
||||
144 - 255 9 110010000 through
|
||||
111111111
|
||||
256 - 279 7 0000000 through
|
||||
0010111
|
||||
280 - 287 8 11000000 through
|
||||
11000111
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 12]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
The code lengths are sufficient to generate the actual codes,
|
||||
as described above; we show the codes in the table for added
|
||||
clarity. Literal/length values 286-287 will never actually
|
||||
occur in the compressed data, but participate in the code
|
||||
construction.
|
||||
|
||||
Distance codes 0-31 are represented by (fixed-length) 5-bit
|
||||
codes, with possible additional bits as shown in the table
|
||||
shown in Paragraph 3.2.5, above. Note that distance codes 30-
|
||||
31 will never actually occur in the compressed data.
|
||||
|
||||
3.2.7. Compression with dynamic Huffman codes (BTYPE=10)
|
||||
|
||||
The Huffman codes for the two alphabets appear in the block
|
||||
immediately after the header bits and before the actual
|
||||
compressed data, first the literal/length code and then the
|
||||
distance code. Each code is defined by a sequence of code
|
||||
lengths, as discussed in Paragraph 3.2.2, above. For even
|
||||
greater compactness, the code length sequences themselves are
|
||||
compressed using a Huffman code. The alphabet for code lengths
|
||||
is as follows:
|
||||
|
||||
0 - 15: Represent code lengths of 0 - 15
|
||||
16: Copy the previous code length 3 - 6 times.
|
||||
The next 2 bits indicate repeat length
|
||||
(0 = 3, ... , 3 = 6)
|
||||
Example: Codes 8, 16 (+2 bits 11),
|
||||
16 (+2 bits 10) will expand to
|
||||
12 code lengths of 8 (1 + 6 + 5)
|
||||
17: Repeat a code length of 0 for 3 - 10 times.
|
||||
(3 bits of length)
|
||||
18: Repeat a code length of 0 for 11 - 138 times
|
||||
(7 bits of length)
|
||||
|
||||
A code length of 0 indicates that the corresponding symbol in
|
||||
the literal/length or distance alphabet will not occur in the
|
||||
block, and should not participate in the Huffman code
|
||||
construction algorithm given earlier. If only one distance
|
||||
code is used, it is encoded using one bit, not zero bits; in
|
||||
this case there is a single code length of one, with one unused
|
||||
code. One distance code of zero bits means that there are no
|
||||
distance codes used at all (the data is all literals).
|
||||
|
||||
We can now define the format of the block:
|
||||
|
||||
5 Bits: HLIT, # of Literal/Length codes - 257 (257 - 286)
|
||||
5 Bits: HDIST, # of Distance codes - 1 (1 - 32)
|
||||
4 Bits: HCLEN, # of Code Length codes - 4 (4 - 19)
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 13]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
(HCLEN + 4) x 3 bits: code lengths for the code length
|
||||
alphabet given just above, in the order: 16, 17, 18,
|
||||
0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
|
||||
|
||||
These code lengths are interpreted as 3-bit integers
|
||||
(0-7); as above, a code length of 0 means the
|
||||
corresponding symbol (literal/length or distance code
|
||||
length) is not used.
|
||||
|
||||
HLIT + 257 code lengths for the literal/length alphabet,
|
||||
encoded using the code length Huffman code
|
||||
|
||||
HDIST + 1 code lengths for the distance alphabet,
|
||||
encoded using the code length Huffman code
|
||||
|
||||
The actual compressed data of the block,
|
||||
encoded using the literal/length and distance Huffman
|
||||
codes
|
||||
|
||||
The literal/length symbol 256 (end of data),
|
||||
encoded using the literal/length Huffman code
|
||||
|
||||
The code length repeat codes can cross from HLIT + 257 to the
|
||||
HDIST + 1 code lengths. In other words, all code lengths form
|
||||
a single sequence of HLIT + HDIST + 258 values.
|
||||
|
||||
3.3. Compliance
|
||||
|
||||
A compressor may limit further the ranges of values specified in
|
||||
the previous section and still be compliant; for example, it may
|
||||
limit the range of backward pointers to some value smaller than
|
||||
32K. Similarly, a compressor may limit the size of blocks so that
|
||||
a compressible block fits in memory.
|
||||
|
||||
A compliant decompressor must accept the full range of possible
|
||||
values defined in the previous section, and must accept blocks of
|
||||
arbitrary size.
|
||||
|
||||
4. Compression algorithm details
|
||||
|
||||
While it is the intent of this document to define the "deflate"
|
||||
compressed data format without reference to any particular
|
||||
compression algorithm, the format is related to the compressed
|
||||
formats produced by LZ77 (Lempel-Ziv 1977, see reference [2] below);
|
||||
since many variations of LZ77 are patented, it is strongly
|
||||
recommended that the implementor of a compressor follow the general
|
||||
algorithm presented here, which is known not to be patented per se.
|
||||
The material in this section is not part of the definition of the
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 14]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
specification per se, and a compressor need not follow it in order to
|
||||
be compliant.
|
||||
|
||||
The compressor terminates a block when it determines that starting a
|
||||
new block with fresh trees would be useful, or when the block size
|
||||
fills up the compressor's block buffer.
|
||||
|
||||
The compressor uses a chained hash table to find duplicated strings,
|
||||
using a hash function that operates on 3-byte sequences. At any
|
||||
given point during compression, let XYZ be the next 3 input bytes to
|
||||
be examined (not necessarily all different, of course). First, the
|
||||
compressor examines the hash chain for XYZ. If the chain is empty,
|
||||
the compressor simply writes out X as a literal byte and advances one
|
||||
byte in the input. If the hash chain is not empty, indicating that
|
||||
the sequence XYZ (or, if we are unlucky, some other 3 bytes with the
|
||||
same hash function value) has occurred recently, the compressor
|
||||
compares all strings on the XYZ hash chain with the actual input data
|
||||
sequence starting at the current point, and selects the longest
|
||||
match.
|
||||
|
||||
The compressor searches the hash chains starting with the most recent
|
||||
strings, to favor small distances and thus take advantage of the
|
||||
Huffman encoding. The hash chains are singly linked. There are no
|
||||
deletions from the hash chains; the algorithm simply discards matches
|
||||
that are too old. To avoid a worst-case situation, very long hash
|
||||
chains are arbitrarily truncated at a certain length, determined by a
|
||||
run-time parameter.
|
||||
|
||||
To improve overall compression, the compressor optionally defers the
|
||||
selection of matches ("lazy matching"): after a match of length N has
|
||||
been found, the compressor searches for a longer match starting at
|
||||
the next input byte. If it finds a longer match, it truncates the
|
||||
previous match to a length of one (thus producing a single literal
|
||||
byte) and then emits the longer match. Otherwise, it emits the
|
||||
original match, and, as described above, advances N bytes before
|
||||
continuing.
|
||||
|
||||
Run-time parameters also control this "lazy match" procedure. If
|
||||
compression ratio is most important, the compressor attempts a
|
||||
complete second search regardless of the length of the first match.
|
||||
In the normal case, if the current match is "long enough", the
|
||||
compressor reduces the search for a longer match, thus speeding up
|
||||
the process. If speed is most important, the compressor inserts new
|
||||
strings in the hash table only when no match was found, or when the
|
||||
match is not "too long". This degrades the compression ratio but
|
||||
saves time since there are both fewer insertions and fewer searches.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 15]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
5. References
|
||||
|
||||
[1] Huffman, D. A., "A Method for the Construction of Minimum
|
||||
Redundancy Codes", Proceedings of the Institute of Radio
|
||||
Engineers, September 1952, Volume 40, Number 9, pp. 1098-1101.
|
||||
|
||||
[2] Ziv J., Lempel A., "A Universal Algorithm for Sequential Data
|
||||
Compression", IEEE Transactions on Information Theory, Vol. 23,
|
||||
No. 3, pp. 337-343.
|
||||
|
||||
[3] Gailly, J.-L., and Adler, M., ZLIB documentation and sources,
|
||||
available in ftp://ftp.uu.net/pub/archiving/zip/doc/
|
||||
|
||||
[4] Gailly, J.-L., and Adler, M., GZIP documentation and sources,
|
||||
available as gzip-*.tar in ftp://prep.ai.mit.edu/pub/gnu/
|
||||
|
||||
[5] Schwartz, E. S., and Kallick, B. "Generating a canonical prefix
|
||||
encoding." Comm. ACM, 7,3 (Mar. 1964), pp. 166-169.
|
||||
|
||||
[6] Hirschberg and Lelewer, "Efficient decoding of prefix codes,"
|
||||
Comm. ACM, 33,4, April 1990, pp. 449-459.
|
||||
|
||||
6. Security Considerations
|
||||
|
||||
Any data compression method involves the reduction of redundancy in
|
||||
the data. Consequently, any corruption of the data is likely to have
|
||||
severe effects and be difficult to correct. Uncompressed text, on
|
||||
the other hand, will probably still be readable despite the presence
|
||||
of some corrupted bytes.
|
||||
|
||||
It is recommended that systems using this data format provide some
|
||||
means of validating the integrity of the compressed data. See
|
||||
reference [3], for example.
|
||||
|
||||
7. Source code
|
||||
|
||||
Source code for a C language implementation of a "deflate" compliant
|
||||
compressor and decompressor is available within the zlib package at
|
||||
ftp://ftp.uu.net/pub/archiving/zip/zlib/.
|
||||
|
||||
8. Acknowledgements
|
||||
|
||||
Trademarks cited in this document are the property of their
|
||||
respective owners.
|
||||
|
||||
Phil Katz designed the deflate format. Jean-Loup Gailly and Mark
|
||||
Adler wrote the related software described in this specification.
|
||||
Glenn Randers-Pehrson converted this document to RFC and HTML format.
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 16]
|
||||
|
||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
||||
|
||||
|
||||
9. Author's Address
|
||||
|
||||
L. Peter Deutsch
|
||||
Aladdin Enterprises
|
||||
203 Santa Margarita Ave.
|
||||
Menlo Park, CA 94025
|
||||
|
||||
Phone: (415) 322-0103 (AM only)
|
||||
FAX: (415) 322-1734
|
||||
EMail: <ghost@aladdin.com>
|
||||
|
||||
Questions about the technical content of this specification can be
|
||||
sent by email to:
|
||||
|
||||
Jean-Loup Gailly <gzip@prep.ai.mit.edu> and
|
||||
Mark Adler <madler@alumni.caltech.edu>
|
||||
|
||||
Editorial comments on this specification can be sent by email to:
|
||||
|
||||
L. Peter Deutsch <ghost@aladdin.com> and
|
||||
Glenn Randers-Pehrson <randeg@alumni.rpi.edu>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 17]
|
||||
|
||||
@@ -1,675 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Network Working Group P. Deutsch
|
||||
Request for Comments: 1952 Aladdin Enterprises
|
||||
Category: Informational May 1996
|
||||
|
||||
|
||||
GZIP file format specification version 4.3
|
||||
|
||||
Status of This Memo
|
||||
|
||||
This memo provides information for the Internet community. This memo
|
||||
does not specify an Internet standard of any kind. Distribution of
|
||||
this memo is unlimited.
|
||||
|
||||
IESG Note:
|
||||
|
||||
The IESG takes no position on the validity of any Intellectual
|
||||
Property Rights statements contained in this document.
|
||||
|
||||
Notices
|
||||
|
||||
Copyright (c) 1996 L. Peter Deutsch
|
||||
|
||||
Permission is granted to copy and distribute this document for any
|
||||
purpose and without charge, including translations into other
|
||||
languages and incorporation into compilations, provided that the
|
||||
copyright notice and this notice are preserved, and that any
|
||||
substantive changes or deletions from the original are clearly
|
||||
marked.
|
||||
|
||||
A pointer to the latest version of this and related documentation in
|
||||
HTML format can be found at the URL
|
||||
<ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html>.
|
||||
|
||||
Abstract
|
||||
|
||||
This specification defines a lossless compressed data format that is
|
||||
compatible with the widely used GZIP utility. The format includes a
|
||||
cyclic redundancy check value for detecting data corruption. The
|
||||
format presently uses the DEFLATE method of compression but can be
|
||||
easily extended to use other compression methods. The format can be
|
||||
implemented readily in a manner not covered by patents.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 1]
|
||||
|
||||
RFC 1952 GZIP File Format Specification May 1996
|
||||
|
||||
|
||||
Table of Contents
|
||||
|
||||
1. Introduction ................................................... 2
|
||||
1.1. Purpose ................................................... 2
|
||||
1.2. Intended audience ......................................... 3
|
||||
1.3. Scope ..................................................... 3
|
||||
1.4. Compliance ................................................ 3
|
||||
1.5. Definitions of terms and conventions used ................. 3
|
||||
1.6. Changes from previous versions ............................ 3
|
||||
2. Detailed specification ......................................... 4
|
||||
2.1. Overall conventions ....................................... 4
|
||||
2.2. File format ............................................... 5
|
||||
2.3. Member format ............................................. 5
|
||||
2.3.1. Member header and trailer ........................... 6
|
||||
2.3.1.1. Extra field ................................... 8
|
||||
2.3.1.2. Compliance .................................... 9
|
||||
3. References .................................................. 9
|
||||
4. Security Considerations .................................... 10
|
||||
5. Acknowledgements ........................................... 10
|
||||
6. Author's Address ........................................... 10
|
||||
7. Appendix: Jean-Loup Gailly's gzip utility .................. 11
|
||||
8. Appendix: Sample CRC Code .................................. 11
|
||||
|
||||
1. Introduction
|
||||
|
||||
1.1. Purpose
|
||||
|
||||
The purpose of this specification is to define a lossless
|
||||
compressed data format that:
|
||||
|
||||
* Is independent of CPU type, operating system, file system,
|
||||
and character set, and hence can be used for interchange;
|
||||
* Can compress or decompress a data stream (as opposed to a
|
||||
randomly accessible file) to produce another data stream,
|
||||
using only an a priori bounded amount of intermediate
|
||||
storage, and hence can be used in data communications or
|
||||
similar structures such as Unix filters;
|
||||
* Compresses data with efficiency comparable to the best
|
||||
currently available general-purpose compression methods,
|
||||
and in particular considerably better than the "compress"
|
||||
program;
|
||||
* Can be implemented readily in a manner not covered by
|
||||
patents, and hence can be practiced freely;
|
||||
* Is compatible with the file format produced by the current
|
||||
widely used gzip utility, in that conforming decompressors
|
||||
will be able to read data produced by the existing gzip
|
||||
compressor.
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 2]
|
||||
|
||||
RFC 1952 GZIP File Format Specification May 1996
|
||||
|
||||
|
||||
The data format defined by this specification does not attempt to:
|
||||
|
||||
* Provide random access to compressed data;
|
||||
* Compress specialized data (e.g., raster graphics) as well as
|
||||
the best currently available specialized algorithms.
|
||||
|
||||
1.2. Intended audience
|
||||
|
||||
This specification is intended for use by implementors of software
|
||||
to compress data into gzip format and/or decompress data from gzip
|
||||
format.
|
||||
|
||||
The text of the specification assumes a basic background in
|
||||
programming at the level of bits and other primitive data
|
||||
representations.
|
||||
|
||||
1.3. Scope
|
||||
|
||||
The specification specifies a compression method and a file format
|
||||
(the latter assuming only that a file can store a sequence of
|
||||
arbitrary bytes). It does not specify any particular interface to
|
||||
a file system or anything about character sets or encodings
|
||||
(except for file names and comments, which are optional).
|
||||
|
||||
1.4. Compliance
|
||||
|
||||
Unless otherwise indicated below, a compliant decompressor must be
|
||||
able to accept and decompress any file that conforms to all the
|
||||
specifications presented here; a compliant compressor must produce
|
||||
files that conform to all the specifications presented here. The
|
||||
material in the appendices is not part of the specification per se
|
||||
and is not relevant to compliance.
|
||||
|
||||
1.5. Definitions of terms and conventions used
|
||||
|
||||
byte: 8 bits stored or transmitted as a unit (same as an octet).
|
||||
(For this specification, a byte is exactly 8 bits, even on
|
||||
machines which store a character on a number of bits different
|
||||
from 8.) See below for the numbering of bits within a byte.
|
||||
|
||||
1.6. Changes from previous versions
|
||||
|
||||
There have been no technical changes to the gzip format since
|
||||
version 4.1 of this specification. In version 4.2, some
|
||||
terminology was changed, and the sample CRC code was rewritten for
|
||||
clarity and to eliminate the requirement for the caller to do pre-
|
||||
and post-conditioning. Version 4.3 is a conversion of the
|
||||
specification to RFC style.
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 3]
|
||||
|
||||
RFC 1952 GZIP File Format Specification May 1996
|
||||
|
||||
|
||||
2. Detailed specification
|
||||
|
||||
2.1. Overall conventions
|
||||
|
||||
In the diagrams below, a box like this:
|
||||
|
||||
+---+
|
||||
| | <-- the vertical bars might be missing
|
||||
+---+
|
||||
|
||||
represents one byte; a box like this:
|
||||
|
||||
+==============+
|
||||
| |
|
||||
+==============+
|
||||
|
||||
represents a variable number of bytes.
|
||||
|
||||
Bytes stored within a computer do not have a "bit order", since
|
||||
they are always treated as a unit. However, a byte considered as
|
||||
an integer between 0 and 255 does have a most- and least-
|
||||
significant bit, and since we write numbers with the most-
|
||||
significant digit on the left, we also write bytes with the most-
|
||||
significant bit on the left. In the diagrams below, we number the
|
||||
bits of a byte so that bit 0 is the least-significant bit, i.e.,
|
||||
the bits are numbered:
|
||||
|
||||
+--------+
|
||||
|76543210|
|
||||
+--------+
|
||||
|
||||
This document does not address the issue of the order in which
|
||||
bits of a byte are transmitted on a bit-sequential medium, since
|
||||
the data format described here is byte- rather than bit-oriented.
|
||||
|
||||
Within a computer, a number may occupy multiple bytes. All
|
||||
multi-byte numbers in the format described here are stored with
|
||||
the least-significant byte first (at the lower memory address).
|
||||
For example, the decimal number 520 is stored as:
|
||||
|
||||
0 1
|
||||
+--------+--------+
|
||||
|00001000|00000010|
|
||||
+--------+--------+
|
||||
^ ^
|
||||
| |
|
||||
| + more significant byte = 2 x 256
|
||||
+ less significant byte = 8
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 4]
|
||||
|
||||
RFC 1952 GZIP File Format Specification May 1996
|
||||
|
||||
|
||||
2.2. File format
|
||||
|
||||
A gzip file consists of a series of "members" (compressed data
|
||||
sets). The format of each member is specified in the following
|
||||
section. The members simply appear one after another in the file,
|
||||
with no additional information before, between, or after them.
|
||||
|
||||
2.3. Member format
|
||||
|
||||
Each member has the following structure:
|
||||
|
||||
+---+---+---+---+---+---+---+---+---+---+
|
||||
|ID1|ID2|CM |FLG| MTIME |XFL|OS | (more-->)
|
||||
+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
(if FLG.FEXTRA set)
|
||||
|
||||
+---+---+=================================+
|
||||
| XLEN |...XLEN bytes of "extra field"...| (more-->)
|
||||
+---+---+=================================+
|
||||
|
||||
(if FLG.FNAME set)
|
||||
|
||||
+=========================================+
|
||||
|...original file name, zero-terminated...| (more-->)
|
||||
+=========================================+
|
||||
|
||||
(if FLG.FCOMMENT set)
|
||||
|
||||
+===================================+
|
||||
|...file comment, zero-terminated...| (more-->)
|
||||
+===================================+
|
||||
|
||||
(if FLG.FHCRC set)
|
||||
|
||||
+---+---+
|
||||
| CRC16 |
|
||||
+---+---+
|
||||
|
||||
+=======================+
|
||||
|...compressed blocks...| (more-->)
|
||||
+=======================+
|
||||
|
||||
0 1 2 3 4 5 6 7
|
||||
+---+---+---+---+---+---+---+---+
|
||||
| CRC32 | ISIZE |
|
||||
+---+---+---+---+---+---+---+---+
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 5]
|
||||
|
||||
RFC 1952 GZIP File Format Specification May 1996
|
||||
|
||||
|
||||
2.3.1. Member header and trailer
|
||||
|
||||
ID1 (IDentification 1)
|
||||
ID2 (IDentification 2)
|
||||
These have the fixed values ID1 = 31 (0x1f, \037), ID2 = 139
|
||||
(0x8b, \213), to identify the file as being in gzip format.
|
||||
|
||||
CM (Compression Method)
|
||||
This identifies the compression method used in the file. CM
|
||||
= 0-7 are reserved. CM = 8 denotes the "deflate"
|
||||
compression method, which is the one customarily used by
|
||||
gzip and which is documented elsewhere.
|
||||
|
||||
FLG (FLaGs)
|
||||
This flag byte is divided into individual bits as follows:
|
||||
|
||||
bit 0 FTEXT
|
||||
bit 1 FHCRC
|
||||
bit 2 FEXTRA
|
||||
bit 3 FNAME
|
||||
bit 4 FCOMMENT
|
||||
bit 5 reserved
|
||||
bit 6 reserved
|
||||
bit 7 reserved
|
||||
|
||||
If FTEXT is set, the file is probably ASCII text. This is
|
||||
an optional indication, which the compressor may set by
|
||||
checking a small amount of the input data to see whether any
|
||||
non-ASCII characters are present. In case of doubt, FTEXT
|
||||
is cleared, indicating binary data. For systems which have
|
||||
different file formats for ascii text and binary data, the
|
||||
decompressor can use FTEXT to choose the appropriate format.
|
||||
We deliberately do not specify the algorithm used to set
|
||||
this bit, since a compressor always has the option of
|
||||
leaving it cleared and a decompressor always has the option
|
||||
of ignoring it and letting some other program handle issues
|
||||
of data conversion.
|
||||
|
||||
If FHCRC is set, a CRC16 for the gzip header is present,
|
||||
immediately before the compressed data. The CRC16 consists
|
||||
of the two least significant bytes of the CRC32 for all
|
||||
bytes of the gzip header up to and not including the CRC16.
|
||||
[The FHCRC bit was never set by versions of gzip up to
|
||||
1.2.4, even though it was documented with a different
|
||||
meaning in gzip 1.2.4.]
|
||||
|
||||
If FEXTRA is set, optional extra fields are present, as
|
||||
described in a following section.
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 6]
|
||||
|
||||
RFC 1952 GZIP File Format Specification May 1996
|
||||
|
||||
|
||||
If FNAME is set, an original file name is present,
|
||||
terminated by a zero byte. The name must consist of ISO
|
||||
8859-1 (LATIN-1) characters; on operating systems using
|
||||
EBCDIC or any other character set for file names, the name
|
||||
must be translated to the ISO LATIN-1 character set. This
|
||||
is the original name of the file being compressed, with any
|
||||
directory components removed, and, if the file being
|
||||
compressed is on a file system with case insensitive names,
|
||||
forced to lower case. There is no original file name if the
|
||||
data was compressed from a source other than a named file;
|
||||
for example, if the source was stdin on a Unix system, there
|
||||
is no file name.
|
||||
|
||||
If FCOMMENT is set, a zero-terminated file comment is
|
||||
present. This comment is not interpreted; it is only
|
||||
intended for human consumption. The comment must consist of
|
||||
ISO 8859-1 (LATIN-1) characters. Line breaks should be
|
||||
denoted by a single line feed character (10 decimal).
|
||||
|
||||
Reserved FLG bits must be zero.
|
||||
|
||||
MTIME (Modification TIME)
|
||||
This gives the most recent modification time of the original
|
||||
file being compressed. The time is in Unix format, i.e.,
|
||||
seconds since 00:00:00 GMT, Jan. 1, 1970. (Note that this
|
||||
may cause problems for MS-DOS and other systems that use
|
||||
local rather than Universal time.) If the compressed data
|
||||
did not come from a file, MTIME is set to the time at which
|
||||
compression started. MTIME = 0 means no time stamp is
|
||||
available.
|
||||
|
||||
XFL (eXtra FLags)
|
||||
These flags are available for use by specific compression
|
||||
methods. The "deflate" method (CM = 8) sets these flags as
|
||||
follows:
|
||||
|
||||
XFL = 2 - compressor used maximum compression,
|
||||
slowest algorithm
|
||||
XFL = 4 - compressor used fastest algorithm
|
||||
|
||||
OS (Operating System)
|
||||
This identifies the type of file system on which compression
|
||||
took place. This may be useful in determining end-of-line
|
||||
convention for text files. The currently defined values are
|
||||
as follows:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 7]
|
||||
|
||||
RFC 1952 GZIP File Format Specification May 1996
|
||||
|
||||
|
||||
0 - FAT filesystem (MS-DOS, OS/2, NT/Win32)
|
||||
1 - Amiga
|
||||
2 - VMS (or OpenVMS)
|
||||
3 - Unix
|
||||
4 - VM/CMS
|
||||
5 - Atari TOS
|
||||
6 - HPFS filesystem (OS/2, NT)
|
||||
7 - Macintosh
|
||||
8 - Z-System
|
||||
9 - CP/M
|
||||
10 - TOPS-20
|
||||
11 - NTFS filesystem (NT)
|
||||
12 - QDOS
|
||||
13 - Acorn RISCOS
|
||||
255 - unknown
|
||||
|
||||
XLEN (eXtra LENgth)
|
||||
If FLG.FEXTRA is set, this gives the length of the optional
|
||||
extra field. See below for details.
|
||||
|
||||
CRC32 (CRC-32)
|
||||
This contains a Cyclic Redundancy Check value of the
|
||||
uncompressed data computed according to CRC-32 algorithm
|
||||
used in the ISO 3309 standard and in section 8.1.1.6.2 of
|
||||
ITU-T recommendation V.42. (See http://www.iso.ch for
|
||||
ordering ISO documents. See gopher://info.itu.ch for an
|
||||
online version of ITU-T V.42.)
|
||||
|
||||
ISIZE (Input SIZE)
|
||||
This contains the size of the original (uncompressed) input
|
||||
data modulo 2^32.
|
||||
|
||||
2.3.1.1. Extra field
|
||||
|
||||
If the FLG.FEXTRA bit is set, an "extra field" is present in
|
||||
the header, with total length XLEN bytes. It consists of a
|
||||
series of subfields, each of the form:
|
||||
|
||||
+---+---+---+---+==================================+
|
||||
|SI1|SI2| LEN |... LEN bytes of subfield data ...|
|
||||
+---+---+---+---+==================================+
|
||||
|
||||
SI1 and SI2 provide a subfield ID, typically two ASCII letters
|
||||
with some mnemonic value. Jean-Loup Gailly
|
||||
<gzip@prep.ai.mit.edu> is maintaining a registry of subfield
|
||||
IDs; please send him any subfield ID you wish to use. Subfield
|
||||
IDs with SI2 = 0 are reserved for future use. The following
|
||||
IDs are currently defined:
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 8]
|
||||
|
||||
RFC 1952 GZIP File Format Specification May 1996
|
||||
|
||||
|
||||
SI1 SI2 Data
|
||||
---------- ---------- ----
|
||||
0x41 ('A') 0x70 ('P') Apollo file type information
|
||||
|
||||
LEN gives the length of the subfield data, excluding the 4
|
||||
initial bytes.
|
||||
|
||||
2.3.1.2. Compliance
|
||||
|
||||
A compliant compressor must produce files with correct ID1,
|
||||
ID2, CM, CRC32, and ISIZE, but may set all the other fields in
|
||||
the fixed-length part of the header to default values (255 for
|
||||
OS, 0 for all others). The compressor must set all reserved
|
||||
bits to zero.
|
||||
|
||||
A compliant decompressor must check ID1, ID2, and CM, and
|
||||
provide an error indication if any of these have incorrect
|
||||
values. It must examine FEXTRA/XLEN, FNAME, FCOMMENT and FHCRC
|
||||
at least so it can skip over the optional fields if they are
|
||||
present. It need not examine any other part of the header or
|
||||
trailer; in particular, a decompressor may ignore FTEXT and OS
|
||||
and always produce binary output, and still be compliant. A
|
||||
compliant decompressor must give an error indication if any
|
||||
reserved bit is non-zero, since such a bit could indicate the
|
||||
presence of a new field that would cause subsequent data to be
|
||||
interpreted incorrectly.
|
||||
|
||||
3. References
|
||||
|
||||
[1] "Information Processing - 8-bit single-byte coded graphic
|
||||
character sets - Part 1: Latin alphabet No.1" (ISO 8859-1:1987).
|
||||
The ISO 8859-1 (Latin-1) character set is a superset of 7-bit
|
||||
ASCII. Files defining this character set are available as
|
||||
iso_8859-1.* in ftp://ftp.uu.net/graphics/png/documents/
|
||||
|
||||
[2] ISO 3309
|
||||
|
||||
[3] ITU-T recommendation V.42
|
||||
|
||||
[4] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification",
|
||||
available in ftp://ftp.uu.net/pub/archiving/zip/doc/
|
||||
|
||||
[5] Gailly, J.-L., GZIP documentation, available as gzip-*.tar in
|
||||
ftp://prep.ai.mit.edu/pub/gnu/
|
||||
|
||||
[6] Sarwate, D.V., "Computation of Cyclic Redundancy Checks via Table
|
||||
Look-Up", Communications of the ACM, 31(8), pp.1008-1013.
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 9]
|
||||
|
||||
RFC 1952 GZIP File Format Specification May 1996
|
||||
|
||||
|
||||
[7] Schwaderer, W.D., "CRC Calculation", April 85 PC Tech Journal,
|
||||
pp.118-133.
|
||||
|
||||
[8] ftp://ftp.adelaide.edu.au/pub/rocksoft/papers/crc_v3.txt,
|
||||
describing the CRC concept.
|
||||
|
||||
4. Security Considerations
|
||||
|
||||
Any data compression method involves the reduction of redundancy in
|
||||
the data. Consequently, any corruption of the data is likely to have
|
||||
severe effects and be difficult to correct. Uncompressed text, on
|
||||
the other hand, will probably still be readable despite the presence
|
||||
of some corrupted bytes.
|
||||
|
||||
It is recommended that systems using this data format provide some
|
||||
means of validating the integrity of the compressed data, such as by
|
||||
setting and checking the CRC-32 check value.
|
||||
|
||||
5. Acknowledgements
|
||||
|
||||
Trademarks cited in this document are the property of their
|
||||
respective owners.
|
||||
|
||||
Jean-Loup Gailly designed the gzip format and wrote, with Mark Adler,
|
||||
the related software described in this specification. Glenn
|
||||
Randers-Pehrson converted this document to RFC and HTML format.
|
||||
|
||||
6. Author's Address
|
||||
|
||||
L. Peter Deutsch
|
||||
Aladdin Enterprises
|
||||
203 Santa Margarita Ave.
|
||||
Menlo Park, CA 94025
|
||||
|
||||
Phone: (415) 322-0103 (AM only)
|
||||
FAX: (415) 322-1734
|
||||
EMail: <ghost@aladdin.com>
|
||||
|
||||
Questions about the technical content of this specification can be
|
||||
sent by email to:
|
||||
|
||||
Jean-Loup Gailly <gzip@prep.ai.mit.edu> and
|
||||
Mark Adler <madler@alumni.caltech.edu>
|
||||
|
||||
Editorial comments on this specification can be sent by email to:
|
||||
|
||||
L. Peter Deutsch <ghost@aladdin.com> and
|
||||
Glenn Randers-Pehrson <randeg@alumni.rpi.edu>
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 10]
|
||||
|
||||
RFC 1952 GZIP File Format Specification May 1996
|
||||
|
||||
|
||||
7. Appendix: Jean-Loup Gailly's gzip utility
|
||||
|
||||
The most widely used implementation of gzip compression, and the
|
||||
original documentation on which this specification is based, were
|
||||
created by Jean-Loup Gailly <gzip@prep.ai.mit.edu>. Since this
|
||||
implementation is a de facto standard, we mention some more of its
|
||||
features here. Again, the material in this section is not part of
|
||||
the specification per se, and implementations need not follow it to
|
||||
be compliant.
|
||||
|
||||
When compressing or decompressing a file, gzip preserves the
|
||||
protection, ownership, and modification time attributes on the local
|
||||
file system, since there is no provision for representing protection
|
||||
attributes in the gzip file format itself. Since the file format
|
||||
includes a modification time, the gzip decompressor provides a
|
||||
command line switch that assigns the modification time from the file,
|
||||
rather than the local modification time of the compressed input, to
|
||||
the decompressed output.
|
||||
|
||||
8. Appendix: Sample CRC Code
|
||||
|
||||
The following sample code represents a practical implementation of
|
||||
the CRC (Cyclic Redundancy Check). (See also ISO 3309 and ITU-T V.42
|
||||
for a formal specification.)
|
||||
|
||||
The sample code is in the ANSI C programming language. Non C users
|
||||
may find it easier to read with these hints:
|
||||
|
||||
& Bitwise AND operator.
|
||||
^ Bitwise exclusive-OR operator.
|
||||
>> Bitwise right shift operator. When applied to an
|
||||
unsigned quantity, as here, right shift inserts zero
|
||||
bit(s) at the left.
|
||||
! Logical NOT operator.
|
||||
++ "n++" increments the variable n.
|
||||
0xNNN 0x introduces a hexadecimal (base 16) constant.
|
||||
Suffix L indicates a long value (at least 32 bits).
|
||||
|
||||
/* Table of CRCs of all 8-bit messages. */
|
||||
unsigned long crc_table[256];
|
||||
|
||||
/* Flag: has the table been computed? Initially false. */
|
||||
int crc_table_computed = 0;
|
||||
|
||||
/* Make the table for a fast CRC. */
|
||||
void make_crc_table(void)
|
||||
{
|
||||
unsigned long c;
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 11]
|
||||
|
||||
RFC 1952 GZIP File Format Specification May 1996
|
||||
|
||||
|
||||
int n, k;
|
||||
for (n = 0; n < 256; n++) {
|
||||
c = (unsigned long) n;
|
||||
for (k = 0; k < 8; k++) {
|
||||
if (c & 1) {
|
||||
c = 0xedb88320L ^ (c >> 1);
|
||||
} else {
|
||||
c = c >> 1;
|
||||
}
|
||||
}
|
||||
crc_table[n] = c;
|
||||
}
|
||||
crc_table_computed = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Update a running crc with the bytes buf[0..len-1] and return
|
||||
the updated crc. The crc should be initialized to zero. Pre- and
|
||||
post-conditioning (one's complement) is performed within this
|
||||
function so it shouldn't be done by the caller. Usage example:
|
||||
|
||||
unsigned long crc = 0L;
|
||||
|
||||
while (read_buffer(buffer, length) != EOF) {
|
||||
crc = update_crc(crc, buffer, length);
|
||||
}
|
||||
if (crc != original_crc) error();
|
||||
*/
|
||||
unsigned long update_crc(unsigned long crc,
|
||||
unsigned char *buf, int len)
|
||||
{
|
||||
unsigned long c = crc ^ 0xffffffffL;
|
||||
int n;
|
||||
|
||||
if (!crc_table_computed)
|
||||
make_crc_table();
|
||||
for (n = 0; n < len; n++) {
|
||||
c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
|
||||
}
|
||||
return c ^ 0xffffffffL;
|
||||
}
|
||||
|
||||
/* Return the CRC of the bytes buf[0..len-1]. */
|
||||
unsigned long crc(unsigned char *buf, int len)
|
||||
{
|
||||
return update_crc(0L, buf, len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Deutsch Informational [Page 12]
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
A Fast Method for Identifying Plain Text Files
|
||||
==============================================
|
||||
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Given a file coming from an unknown source, it is sometimes desirable
|
||||
to find out whether the format of that file is plain text. Although
|
||||
this may appear like a simple task, a fully accurate detection of the
|
||||
file type requires heavy-duty semantic analysis on the file contents.
|
||||
It is, however, possible to obtain satisfactory results by employing
|
||||
various heuristics.
|
||||
|
||||
Previous versions of PKZip and other zip-compatible compression tools
|
||||
were using a crude detection scheme: if more than 80% (4/5) of the bytes
|
||||
found in a certain buffer are within the range [7..127], the file is
|
||||
labeled as plain text, otherwise it is labeled as binary. A prominent
|
||||
limitation of this scheme is the restriction to Latin-based alphabets.
|
||||
Other alphabets, like Greek, Cyrillic or Asian, make extensive use of
|
||||
the bytes within the range [128..255], and texts using these alphabets
|
||||
are most often misidentified by this scheme; in other words, the rate
|
||||
of false negatives is sometimes too high, which means that the recall
|
||||
is low. Another weakness of this scheme is a reduced precision, due to
|
||||
the false positives that may occur when binary files containing large
|
||||
amounts of textual characters are misidentified as plain text.
|
||||
|
||||
In this article we propose a new, simple detection scheme that features
|
||||
a much increased precision and a near-100% recall. This scheme is
|
||||
designed to work on ASCII, Unicode and other ASCII-derived alphabets,
|
||||
and it handles single-byte encodings (ISO-8859, MacRoman, KOI8, etc.)
|
||||
and variable-sized encodings (ISO-2022, UTF-8, etc.). Wider encodings
|
||||
(UCS-2/UTF-16 and UCS-4/UTF-32) are not handled, however.
|
||||
|
||||
|
||||
The Algorithm
|
||||
-------------
|
||||
|
||||
The algorithm works by dividing the set of bytecodes [0..255] into three
|
||||
categories:
|
||||
- The white list of textual bytecodes:
|
||||
9 (TAB), 10 (LF), 13 (CR), 32 (SPACE) to 255.
|
||||
- The gray list of tolerated bytecodes:
|
||||
7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB), 27 (ESC).
|
||||
- The black list of undesired, non-textual bytecodes:
|
||||
0 (NUL) to 6, 14 to 31.
|
||||
|
||||
If a file contains at least one byte that belongs to the white list and
|
||||
no byte that belongs to the black list, then the file is categorized as
|
||||
plain text; otherwise, it is categorized as binary. (The boundary case,
|
||||
when the file is empty, automatically falls into the latter category.)
|
||||
|
||||
|
||||
Rationale
|
||||
---------
|
||||
|
||||
The idea behind this algorithm relies on two observations.
|
||||
|
||||
The first observation is that, although the full range of 7-bit codes
|
||||
[0..127] is properly specified by the ASCII standard, most control
|
||||
characters in the range [0..31] are not used in practice. The only
|
||||
widely-used, almost universally-portable control codes are 9 (TAB),
|
||||
10 (LF) and 13 (CR). There are a few more control codes that are
|
||||
recognized on a reduced range of platforms and text viewers/editors:
|
||||
7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB) and 27 (ESC); but these
|
||||
codes are rarely (if ever) used alone, without being accompanied by
|
||||
some printable text. Even the newer, portable text formats such as
|
||||
XML avoid using control characters outside the list mentioned here.
|
||||
|
||||
The second observation is that most of the binary files tend to contain
|
||||
control characters, especially 0 (NUL). Even though the older text
|
||||
detection schemes observe the presence of non-ASCII codes from the range
|
||||
[128..255], the precision rarely has to suffer if this upper range is
|
||||
labeled as textual, because the files that are genuinely binary tend to
|
||||
contain both control characters and codes from the upper range. On the
|
||||
other hand, the upper range needs to be labeled as textual, because it
|
||||
is used by virtually all ASCII extensions. In particular, this range is
|
||||
used for encoding non-Latin scripts.
|
||||
|
||||
Since there is no counting involved, other than simply observing the
|
||||
presence or the absence of some byte values, the algorithm produces
|
||||
consistent results, regardless what alphabet encoding is being used.
|
||||
(If counting were involved, it could be possible to obtain different
|
||||
results on a text encoded, say, using ISO-8859-16 versus UTF-8.)
|
||||
|
||||
There is an extra category of plain text files that are "polluted" with
|
||||
one or more black-listed codes, either by mistake or by peculiar design
|
||||
considerations. In such cases, a scheme that tolerates a small fraction
|
||||
of black-listed codes would provide an increased recall (i.e. more true
|
||||
positives). This, however, incurs a reduced precision overall, since
|
||||
false positives are more likely to appear in binary files that contain
|
||||
large chunks of textual data. Furthermore, "polluted" plain text should
|
||||
be regarded as binary by general-purpose text detection schemes, because
|
||||
general-purpose text processing algorithms might not be applicable.
|
||||
Under this premise, it is safe to say that our detection method provides
|
||||
a near-100% recall.
|
||||
|
||||
Experiments have been run on many files coming from various platforms
|
||||
and applications. We tried plain text files, system logs, source code,
|
||||
formatted office documents, compiled object code, etc. The results
|
||||
confirm the optimistic assumptions about the capabilities of this
|
||||
algorithm.
|
||||
|
||||
|
||||
--
|
||||
Cosmin Truta
|
||||
Last updated: 2006-May-28
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/* gzlib.c -- zlib functions common to reading and writing gzip files
|
||||
* Copyright (C) 2004, 2010, 2011, 2012, 2013, 2016 Mark Adler
|
||||
* Copyright (C) 2004-2017 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* gzwrite.c -- zlib functions for writing gzip files
|
||||
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler
|
||||
* Copyright (C) 2004-2017 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* inffast.c -- fast decoding
|
||||
* Copyright (C) 1995-2008, 2010, 2013, 2016 Mark Adler
|
||||
* Copyright (C) 1995-2017 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#define MAXBITS 15
|
||||
|
||||
const char inflate_copyright[] =
|
||||
" inflate 1.2.10 Copyright 1995-2017 Mark Adler ";
|
||||
" inflate 1.2.11 Copyright 1995-2017 Mark Adler ";
|
||||
/*
|
||||
If you use the zlib library in a product, an acknowledgment is welcome
|
||||
in the documentation of your product. If for some reason you cannot
|
||||
@@ -62,7 +62,7 @@ unsigned short FAR *work;
|
||||
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
|
||||
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
|
||||
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 192, 202};
|
||||
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 77, 202};
|
||||
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
|
||||
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
|
||||
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
ZLIB version 1.2.10 for OS/400 installation instructions
|
||||
ZLIB version 1.2.11 for OS/400 installation instructions
|
||||
|
||||
1) Download and unpack the zlib tarball to some IFS directory.
|
||||
(i.e.: /path/to/the/zlib/ifs/source/directory)
|
||||
|
||||
@@ -260,7 +260,7 @@ fi
|
||||
echo '#pragma comment(user, "ZLIB version '"${VERSION}"'")' > os400.c
|
||||
echo '#pragma comment(user, __DATE__)' >> os400.c
|
||||
echo '#pragma comment(user, __TIME__)' >> os400.c
|
||||
echo '#pragma comment(copyright, "Copyright (C) 1995-2016 Jean-Loup Gailly, Mark Adler. OS/400 version by P. Monnerat.")' >> os400.c
|
||||
echo '#pragma comment(copyright, "Copyright (C) 1995-2017 Jean-Loup Gailly, Mark Adler. OS/400 version by P. Monnerat.")' >> os400.c
|
||||
make_module OS400 os400.c
|
||||
LINK= # No need to rebuild service program yet.
|
||||
MODULES=
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
* ZLIB.INC - Interface to the general purpose compression library
|
||||
*
|
||||
* ILE RPG400 version by Patrick Monnerat, DATASPHERE.
|
||||
* Version 1.2.10
|
||||
* Version 1.2.11
|
||||
*
|
||||
*
|
||||
* WARNING:
|
||||
@@ -22,12 +22,12 @@
|
||||
*
|
||||
* Versioning information.
|
||||
*
|
||||
D ZLIB_VERSION C '1.2.10'
|
||||
D ZLIB_VERSION C '1.2.11'
|
||||
D ZLIB_VERNUM C X'12a0'
|
||||
D ZLIB_VER_MAJOR C 1
|
||||
D ZLIB_VER_MINOR C 2
|
||||
D ZLIB_VER_REVISION...
|
||||
D C 10
|
||||
D C 11
|
||||
D ZLIB_VER_SUBREVISION...
|
||||
D C 0
|
||||
*
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
<QPG:Files>
|
||||
<QPG:Add file="../zconf.h" install="/opt/include/" user="root:sys" permission="644"/>
|
||||
<QPG:Add file="../zlib.h" install="/opt/include/" user="root:sys" permission="644"/>
|
||||
<QPG:Add file="../libz.so.1.2.10" install="/opt/lib/" user="root:bin" permission="644"/>
|
||||
<QPG:Add file="libz.so" install="/opt/lib/" component="dev" filetype="symlink" linkto="libz.so.1.2.10"/>
|
||||
<QPG:Add file="libz.so.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.2.10"/>
|
||||
<QPG:Add file="../libz.so.1.2.10" install="/opt/lib/" component="slib"/>
|
||||
<QPG:Add file="../libz.so.1.2.11" install="/opt/lib/" user="root:bin" permission="644"/>
|
||||
<QPG:Add file="libz.so" install="/opt/lib/" component="dev" filetype="symlink" linkto="libz.so.1.2.11"/>
|
||||
<QPG:Add file="libz.so.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.2.11"/>
|
||||
<QPG:Add file="../libz.so.1.2.11" install="/opt/lib/" component="slib"/>
|
||||
</QPG:Files>
|
||||
|
||||
<QPG:PackageFilter>
|
||||
@@ -63,7 +63,7 @@
|
||||
</QPM:ProductDescription>
|
||||
|
||||
<QPM:ReleaseDescription>
|
||||
<QPM:ReleaseVersion>1.2.10</QPM:ReleaseVersion>
|
||||
<QPM:ReleaseVersion>1.2.11</QPM:ReleaseVersion>
|
||||
<QPM:ReleaseUrgency>Medium</QPM:ReleaseUrgency>
|
||||
<QPM:ReleaseStability>Stable</QPM:ReleaseStability>
|
||||
<QPM:ReleaseNoteMinor></QPM:ReleaseNoteMinor>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" ?>
|
||||
<package name="zlib" version="1.2.10">
|
||||
<library name="zlib" dlversion="1.2.10" dlname="z">
|
||||
<package name="zlib" version="1.2.11">
|
||||
<library name="zlib" dlversion="1.2.11" dlname="z">
|
||||
<property name="description"> zip compression library </property>
|
||||
<property name="include-target-dir" value="$(@PACKAGE/install-includedir)" />
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/* trees.c -- output deflated data using Huffman coding
|
||||
* Copyright (C) 1995-2016 Jean-loup Gailly
|
||||
* Copyright (C) 1995-2017 Jean-loup Gailly
|
||||
* detect_data_type() function provided freely by Cosmin Truta, 2006
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
@@ -906,7 +906,7 @@ void ZLIB_INTERNAL _tr_align(s)
|
||||
|
||||
/* ===========================================================================
|
||||
* Determine the best encoding for the current block: dynamic trees, static
|
||||
* trees or store, and output the encoded block to the zip file.
|
||||
* trees or store, and write out the encoded block.
|
||||
*/
|
||||
void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
|
||||
deflate_state *s;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Makefile for zlib using Microsoft (Visual) C
|
||||
# zlib is copyright (C) 1995-2006 Jean-loup Gailly and Mark Adler
|
||||
# zlib is copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
|
||||
#
|
||||
# Usage:
|
||||
# nmake -f win32/Makefile.msc (standard build)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
ZLIB DATA COMPRESSION LIBRARY
|
||||
|
||||
zlib 1.2.10 is a general purpose data compression library. All the code is
|
||||
zlib 1.2.11 is a general purpose data compression library. All the code is
|
||||
thread safe. The data format used by the zlib library is described by RFCs
|
||||
(Request for Comments) 1950 to 1952 in the files
|
||||
http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
|
||||
@@ -22,7 +22,7 @@ before asking for help.
|
||||
|
||||
Manifest:
|
||||
|
||||
The package zlib-1.2.10-win32-x86.zip will contain the following files:
|
||||
The package zlib-1.2.11-win32-x86.zip will contain the following files:
|
||||
|
||||
README-WIN32.txt This document
|
||||
ChangeLog Changes since previous zlib packages
|
||||
@@ -72,7 +72,7 @@ are too numerous to cite here.
|
||||
|
||||
Copyright notice:
|
||||
|
||||
(C) 1995-2012 Jean-loup Gailly and Mark Adler
|
||||
(C) 1995-2017 Jean-loup Gailly and Mark Adler
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -6,7 +6,7 @@ What's here
|
||||
|
||||
Source
|
||||
======
|
||||
zlib version 1.2.10
|
||||
zlib version 1.2.11
|
||||
available at http://www.gzip.org/zlib/
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ Build info
|
||||
|
||||
Copyright notice
|
||||
================
|
||||
Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler
|
||||
Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
Installing ZLIB1.DLL
|
||||
====================
|
||||
Copy ZLIB1.DLL to the SYSTEM or the SYSTEM32 directory.
|
||||
|
||||
If you want to install the 32-bit dll on a 64-bit
|
||||
machine, use the SysWOW64 directory instead.
|
||||
|
||||
|
||||
Using ZLIB1.DLL with Microsoft Visual C++
|
||||
@@ -20,12 +23,17 @@ Using ZLIB1.DLL with gcc/MinGW
|
||||
1. Install the supplied header files "zlib.h" and "zconf.h"
|
||||
into the INCLUDE directory.
|
||||
|
||||
2. Copy the supplied library file "zdll.lib" to "libzdll.a":
|
||||
2. (32-bit): Copy the supplied library file "zdll.lib" to "libzdll.a":
|
||||
cp lib/zdll.lib lib/libzdll.a
|
||||
|
||||
OR
|
||||
|
||||
2' Build the import library from the supplied "zlib.def":
|
||||
2'. (64-bit): Copy the supplied library file "libz.dll.a" to "libzdll.a":
|
||||
cp lib/libz.dll.a lib/libzdll.a
|
||||
|
||||
OR
|
||||
|
||||
2'' Build the import library from the supplied "zlib.def":
|
||||
dlltool -D zlib1.dll -d lib/zlib.def -l lib/libzdll.a
|
||||
|
||||
3. Install "libzdll.a" into the LIB directory.
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
|
||||
To build zlib using the Microsoft Visual C++ environment,
|
||||
use the appropriate project from the projects/ directory.
|
||||
use the appropriate project from the contrib/vstudio/ directory.
|
||||
|
||||
Regular → Executable
BIN
Binary file not shown.
Binary file not shown.
@@ -26,7 +26,7 @@ BEGIN
|
||||
VALUE "FileDescription", "zlib data compression library\0"
|
||||
VALUE "FileVersion", ZLIB_VERSION "\0"
|
||||
VALUE "InternalName", "zlib1.dll\0"
|
||||
VALUE "LegalCopyright", "(C) 1995-2013 Jean-loup Gailly & Mark Adler\0"
|
||||
VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0"
|
||||
VALUE "OriginalFilename", "zlib1.dll\0"
|
||||
VALUE "ProductName", "zlib\0"
|
||||
VALUE "ProductVersion", ZLIB_VERSION "\0"
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2
-2
@@ -1,4 +1,4 @@
|
||||
.TH ZLIB 3 "2 Jan 2017"
|
||||
.TH ZLIB 3 "15 Jan 2017"
|
||||
.SH NAME
|
||||
zlib \- compression/decompression library
|
||||
.SH SYNOPSIS
|
||||
@@ -105,7 +105,7 @@ before asking for help.
|
||||
Send questions and/or comments to zlib@gzip.org,
|
||||
or (for the Windows DLL version) to Gilles Vollant (info@winimage.com).
|
||||
.SH AUTHORS AND LICENSE
|
||||
Version 1.2.10
|
||||
Version 1.2.11
|
||||
.LP
|
||||
Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
|
||||
.LP
|
||||
|
||||
Binary file not shown.
+9
-8
@@ -1,5 +1,5 @@
|
||||
/* zlib.h -- interface of the 'zlib' general purpose compression library
|
||||
version 1.2.10, January 2nd, 2017
|
||||
version 1.2.11, January 15th, 2017
|
||||
|
||||
Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
|
||||
|
||||
@@ -37,11 +37,11 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ZLIB_VERSION "1.2.10"
|
||||
#define ZLIB_VERNUM 0x12a0
|
||||
#define ZLIB_VERSION "1.2.11"
|
||||
#define ZLIB_VERNUM 0x12b0
|
||||
#define ZLIB_VER_MAJOR 1
|
||||
#define ZLIB_VER_MINOR 2
|
||||
#define ZLIB_VER_REVISION 10
|
||||
#define ZLIB_VER_REVISION 11
|
||||
#define ZLIB_VER_SUBREVISION 0
|
||||
|
||||
/*
|
||||
@@ -712,10 +712,11 @@ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
|
||||
used to switch between compression and straight copy of the input data, or
|
||||
to switch to a different kind of input data requiring a different strategy.
|
||||
If the compression approach (which is a function of the level) or the
|
||||
strategy is changed, then the input available so far is compressed with the
|
||||
old level and strategy using deflate(strm, Z_BLOCK). There are three
|
||||
approaches for the compression levels 0, 1..3, and 4..9 respectively. The
|
||||
new level and strategy will take effect at the next call of deflate().
|
||||
strategy is changed, and if any input has been consumed in a previous
|
||||
deflate() call, then the input available so far is compressed with the old
|
||||
level and strategy using deflate(strm, Z_BLOCK). There are three approaches
|
||||
for the compression levels 0, 1..3, and 4..9 respectively. The new level
|
||||
and strategy will take effect at the next call of deflate().
|
||||
|
||||
If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does
|
||||
not have enough output space to complete, then the parameter change will not
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/* zutil.c -- target dependent utility functions for the compression library
|
||||
* Copyright (C) 1995-2005, 2010, 2011, 2012, 2016 Jean-loup Gailly
|
||||
* Copyright (C) 1995-2017 Jean-loup Gailly
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
||||
+1
-1
@@ -205,7 +205,7 @@ and sets \fIinterp\fR's result to an error message indicating that
|
||||
the \fBreturn\fR, \fBbreak\fR, or \fBcontinue\fR command was
|
||||
invoked in an inappropriate place.
|
||||
This means that top-level applications should never see a return code
|
||||
from \fBTcl_EvalObjEx\fR other then \fBTCL_OK\fR or \fBTCL_ERROR\fR.
|
||||
from \fBTcl_EvalObjEx\fR other than \fBTCL_OK\fR or \fBTCL_ERROR\fR.
|
||||
|
||||
.SH KEYWORDS
|
||||
execute, file, global, result, script, value
|
||||
|
||||
+1
-1
@@ -97,7 +97,7 @@ are provided by the C language standard. The \fBTcl_WideInt\fR type is a
|
||||
typedef defined to be whatever signed integral type covers at least the
|
||||
64-bit integer range (-9223372036854775808 to 9223372036854775807). Depending
|
||||
on the platform and the C compiler, the actual type might be
|
||||
\fBlong int\fR, \fBlong long int\fR, \fBint64\fR, or something else.
|
||||
\fBlong int\fR, \fBlong long int\fR, \fB__int64\fR, or something else.
|
||||
The \fBmp_int\fR type is a multiple-precision integer type defined
|
||||
by the LibTomMath multiple-precision integer library.
|
||||
.PP
|
||||
|
||||
+36
-12
@@ -61,7 +61,9 @@ The C variable is of type \fBint\fR.
|
||||
Any value written into the Tcl variable must have a proper integer
|
||||
form acceptable to \fBTcl_GetIntFromObj\fR; attempts to write
|
||||
non-integer values into \fIvarName\fR will be rejected with
|
||||
Tcl errors.
|
||||
Tcl errors. Incomplete integer representations (like the empty
|
||||
string, '+', '-' or the hex/octal/binary prefix) are accepted
|
||||
as if they are valid too.
|
||||
.TP
|
||||
\fBTCL_LINK_UINT\fR
|
||||
The C variable is of type \fBunsigned int\fR.
|
||||
@@ -69,14 +71,18 @@ Any value written into the Tcl variable must have a proper unsigned
|
||||
integer form acceptable to \fBTcl_GetWideIntFromObj\fR and in the
|
||||
platform's defined range for the \fBunsigned int\fR type; attempts to
|
||||
write non-integer values (or values outside the range) into
|
||||
\fIvarName\fR will be rejected with Tcl errors.
|
||||
\fIvarName\fR will be rejected with Tcl errors. Incomplete integer
|
||||
representations (like the empty string, '+', '-' or the hex/octal/binary
|
||||
prefix) are accepted as if they are valid too.
|
||||
.TP
|
||||
\fBTCL_LINK_CHAR\fR
|
||||
The C variable is of type \fBchar\fR.
|
||||
Any value written into the Tcl variable must have a proper integer
|
||||
form acceptable to \fBTcl_GetIntFromObj\fR and be in the range of the
|
||||
\fBchar\fR datatype; attempts to write non-integer or out-of-range
|
||||
values into \fIvarName\fR will be rejected with Tcl errors.
|
||||
values into \fIvarName\fR will be rejected with Tcl errors. Incomplete
|
||||
integer representations (like the empty string, '+', '-' or the
|
||||
hex/octal/binary prefix) are accepted as if they are valid too.
|
||||
.TP
|
||||
\fBTCL_LINK_UCHAR\fR
|
||||
The C variable is of type \fBunsigned char\fR.
|
||||
@@ -84,14 +90,18 @@ Any value written into the Tcl variable must have a proper unsigned
|
||||
integer form acceptable to \fBTcl_GetIntFromObj\fR and in the
|
||||
platform's defined range for the \fBunsigned char\fR type; attempts to
|
||||
write non-integer values (or values outside the range) into
|
||||
\fIvarName\fR will be rejected with Tcl errors.
|
||||
\fIvarName\fR will be rejected with Tcl errors. Incomplete integer
|
||||
representations (like the empty string, '+', '-' or the hex/octal/binary
|
||||
prefix) are accepted as if they are valid too.
|
||||
.TP
|
||||
\fBTCL_LINK_SHORT\fR
|
||||
The C variable is of type \fBshort\fR.
|
||||
Any value written into the Tcl variable must have a proper integer
|
||||
form acceptable to \fBTcl_GetIntFromObj\fR and be in the range of the
|
||||
\fBshort\fR datatype; attempts to write non-integer or out-of-range
|
||||
values into \fIvarName\fR will be rejected with Tcl errors.
|
||||
values into \fIvarName\fR will be rejected with Tcl errors. Incomplete
|
||||
integer representations (like the empty string, '+', '-' or the
|
||||
hex/octal/binary prefix) are accepted as if they are valid too.
|
||||
.TP
|
||||
\fBTCL_LINK_USHORT\fR
|
||||
The C variable is of type \fBunsigned short\fR.
|
||||
@@ -99,14 +109,18 @@ Any value written into the Tcl variable must have a proper unsigned
|
||||
integer form acceptable to \fBTcl_GetIntFromObj\fR and in the
|
||||
platform's defined range for the \fBunsigned short\fR type; attempts to
|
||||
write non-integer values (or values outside the range) into
|
||||
\fIvarName\fR will be rejected with Tcl errors.
|
||||
\fIvarName\fR will be rejected with Tcl errors. Incomplete integer
|
||||
representations (like the empty string, '+', '-' or the hex/octal/binary
|
||||
prefix) are accepted as if they are valid too.
|
||||
.TP
|
||||
\fBTCL_LINK_LONG\fR
|
||||
The C variable is of type \fBlong\fR.
|
||||
Any value written into the Tcl variable must have a proper integer
|
||||
form acceptable to \fBTcl_GetLongFromObj\fR; attempts to write
|
||||
non-integer or out-of-range
|
||||
values into \fIvarName\fR will be rejected with Tcl errors.
|
||||
values into \fIvarName\fR will be rejected with Tcl errors. Incomplete
|
||||
integer representations (like the empty string, '+', '-' or the
|
||||
hex/octal/binary prefix) are accepted as if they are valid too.
|
||||
.TP
|
||||
\fBTCL_LINK_ULONG\fR
|
||||
The C variable is of type \fBunsigned long\fR.
|
||||
@@ -114,14 +128,18 @@ Any value written into the Tcl variable must have a proper unsigned
|
||||
integer form acceptable to \fBTcl_GetWideIntFromObj\fR and in the
|
||||
platform's defined range for the \fBunsigned long\fR type; attempts to
|
||||
write non-integer values (or values outside the range) into
|
||||
\fIvarName\fR will be rejected with Tcl errors.
|
||||
\fIvarName\fR will be rejected with Tcl errors. Incomplete integer
|
||||
representations (like the empty string, '+', '-' or the hex/octal/binary
|
||||
prefix) are accepted as if they are valid too.
|
||||
.TP
|
||||
\fBTCL_LINK_DOUBLE\fR
|
||||
The C variable is of type \fBdouble\fR.
|
||||
Any value written into the Tcl variable must have a proper real
|
||||
form acceptable to \fBTcl_GetDoubleFromObj\fR; attempts to write
|
||||
non-real values into \fIvarName\fR will be rejected with
|
||||
Tcl errors.
|
||||
Tcl errors. Incomplete integer or real representations (like the
|
||||
empty string, '.', '+', '-' or the hex/octal/binary prefix) are
|
||||
accepted as if they are valid too.
|
||||
.TP
|
||||
\fBTCL_LINK_FLOAT\fR
|
||||
The C variable is of type \fBfloat\fR.
|
||||
@@ -129,7 +147,9 @@ Any value written into the Tcl variable must have a proper real
|
||||
form acceptable to \fBTcl_GetDoubleFromObj\fR and must be within the
|
||||
range acceptable for a \fBfloat\fR; attempts to
|
||||
write non-real values (or values outside the range) into
|
||||
\fIvarName\fR will be rejected with Tcl errors.
|
||||
\fIvarName\fR will be rejected with Tcl errors. Incomplete integer
|
||||
or real representations (like the empty string, '.', '+', '-' or
|
||||
the hex/octal/binary prefix) are accepted as if they are valid too.
|
||||
.TP
|
||||
\fBTCL_LINK_WIDE_INT\fR
|
||||
The C variable is of type \fBTcl_WideInt\fR (which is an integer type
|
||||
@@ -137,7 +157,9 @@ at least 64-bits wide on all platforms that can support it.)
|
||||
Any value written into the Tcl variable must have a proper integer
|
||||
form acceptable to \fBTcl_GetWideIntFromObj\fR; attempts to write
|
||||
non-integer values into \fIvarName\fR will be rejected with
|
||||
Tcl errors.
|
||||
Tcl errors. Incomplete integer representations (like the empty
|
||||
string, '+', '-' or the hex/octal/binary prefix) are accepted
|
||||
as if they are valid too.
|
||||
.TP
|
||||
\fBTCL_LINK_WIDE_UINT\fR
|
||||
The C variable is of type \fBTcl_WideUInt\fR (which is an unsigned
|
||||
@@ -148,7 +170,9 @@ integer form acceptable to \fBTcl_GetWideIntFromObj\fR (it will be
|
||||
cast to unsigned);
|
||||
.\" FIXME! Use bignums instead.
|
||||
attempts to write non-integer values into \fIvarName\fR will be
|
||||
rejected with Tcl errors.
|
||||
rejected with Tcl errors. Incomplete integer representations (like
|
||||
the empty string, '+', '-' or the hex/octal/binary prefix) are accepted
|
||||
as if they are valid too.
|
||||
.TP
|
||||
\fBTCL_LINK_BOOLEAN\fR
|
||||
The C variable is of type \fBint\fR.
|
||||
|
||||
@@ -32,8 +32,6 @@ the command at global level instead of the current stack level.
|
||||
.PP
|
||||
\fBTcl_RecordAndEvalObj\fR is invoked to record a command as an event
|
||||
on the history list and then execute it using \fBTcl_EvalObjEx\fR
|
||||
(or \fBTcl_GlobalEvalObj\fR if the \fBTCL_EVAL_GLOBAL\fR bit is set
|
||||
in \fIflags\fR).
|
||||
It returns a completion code such as \fBTCL_OK\fR just like \fBTcl_EvalObjEx\fR,
|
||||
as well as a result value containing additional information
|
||||
(a result value or error message)
|
||||
|
||||
+1
-1
@@ -297,7 +297,7 @@ scripts are stored.
|
||||
This is actually the value of the \fBtcl_library\fR
|
||||
variable and may be changed by setting \fBtcl_library\fR.
|
||||
.TP
|
||||
\fBinfo loaded \fR?\fIinterp\fR? \fR?\fIpackage\fR?
|
||||
\fBinfo loaded \fR?\fIinterp\fR? ?\fIpackage\fR?
|
||||
.
|
||||
Returns the filename loaded as part of \fIpackage\fR. If \fIpackage\fR
|
||||
is not specified, returns a list describing all of the packages
|
||||
|
||||
+2
-1
@@ -40,7 +40,8 @@ except (a) case is ignored except as a tie-breaker and (b) if two
|
||||
strings contain embedded numbers, the numbers compare as integers,
|
||||
not characters. For example, in \fB\-dictionary\fR mode, \fBbigBoy\fR
|
||||
sorts between \fBbigbang\fR and \fBbigboy\fR, and \fBx10y\fR
|
||||
sorts between \fBx9y\fR and \fBx11y\fR.
|
||||
sorts between \fBx9y\fR and \fBx11y\fR. Overrides the \fB\-nocase\fR
|
||||
option.
|
||||
.TP
|
||||
\fB\-integer\fR
|
||||
.
|
||||
|
||||
+3
-3
@@ -293,12 +293,12 @@ treatment is as if the enclosing delimiters were
|
||||
.QW \fB[.\fR \&
|
||||
and
|
||||
.QW \fB.]\fR .)
|
||||
For example, if \fBo\fR and \fB\*(qo\fR are the members of an
|
||||
For example, if \fBo\fR and \fB\[^o]\fR are the members of an
|
||||
equivalence class, then
|
||||
.QW \fB[[=o=]]\fR ,
|
||||
.QW \fB[[=\*(qo=]]\fR ,
|
||||
.QW \fB[[=\[^o]=]]\fR ,
|
||||
and
|
||||
.QW \fB[o\*(qo]\fR \&
|
||||
.QW \fB[o\[^o]]\fR \&
|
||||
are all synonymous. An equivalence class may not be an endpoint of a range.
|
||||
.RS
|
||||
.PP
|
||||
|
||||
+1
-1
@@ -1059,7 +1059,7 @@ declare 293 {
|
||||
int Tcl_EvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags)
|
||||
}
|
||||
declare 294 {
|
||||
void Tcl_ExitThread(int status)
|
||||
TCL_NORETURN void Tcl_ExitThread(int status)
|
||||
}
|
||||
declare 295 {
|
||||
int Tcl_ExternalToUtf(Tcl_Interp *interp, Tcl_Encoding encoding,
|
||||
|
||||
+25
-23
@@ -41,7 +41,6 @@ extern "C" {
|
||||
* unix/configure.ac (2 LOC Major, 2 LOC minor, 1 LOC patch)
|
||||
* win/configure.ac (as above)
|
||||
* win/tcl.m4 (not patchlevel)
|
||||
* win/makefile.bc (not patchlevel) 2 LOC
|
||||
* README (sections 0 and 2, with and without separator)
|
||||
* macosx/Tcl.pbproj/project.pbxproj (not patchlevel) 1 LOC
|
||||
* macosx/Tcl.pbproj/default.pbxuser (not patchlevel) 1 LOC
|
||||
@@ -61,6 +60,7 @@ extern "C" {
|
||||
#define TCL_VERSION "8.7"
|
||||
#define TCL_PATCH_LEVEL "8.7a0"
|
||||
|
||||
#if !defined(TCL_NO_DEPRECATED) || defined(RC_INVOKED)
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* The following definitions set up the proper options for Windows compilers.
|
||||
@@ -89,6 +89,7 @@ extern "C" {
|
||||
# define JOIN(a,b) JOIN1(a,b)
|
||||
# define JOIN1(a,b) a##b
|
||||
#endif
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
* A special definition used to allow this header file to be included from
|
||||
@@ -140,7 +141,7 @@ extern "C" {
|
||||
# define TCL_VARARGS(type, name) (type name, ...)
|
||||
# define TCL_VARARGS_DEF(type, name) (type name, ...)
|
||||
# define TCL_VARARGS_START(type, name, list) (va_start(list, name), name)
|
||||
#endif
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
#if defined(__GNUC__) && (__GNUC__ > 2)
|
||||
# define TCL_FORMAT_PRINTF(a,b) __attribute__ ((__format__ (__printf__, a, b)))
|
||||
# define TCL_NORETURN __attribute__ ((noreturn))
|
||||
@@ -256,7 +257,7 @@ extern "C" {
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
# undef _ANSI_ARGS_
|
||||
# define _ANSI_ARGS_(x) x
|
||||
#endif
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
* Definitions that allow this header file to be used either with or without
|
||||
@@ -376,8 +377,8 @@ typedef long LONG;
|
||||
* 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
|
||||
* 64-bit system.)
|
||||
* TCL_WIDE_INT_IS_LONG - if wide ints are really longs (i.e. we're on a
|
||||
* LP64 system such as modern Solaris or Linux ... not including Win64)
|
||||
* Tcl_WideAsLong - forgetful converter from wideInt to long.
|
||||
* Tcl_LongAsWide - sign-extending converter from long to wideInt.
|
||||
* Tcl_WideAsDouble - converter from wideInt to double.
|
||||
@@ -394,11 +395,7 @@ typedef long LONG;
|
||||
#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__ */
|
||||
# define TCL_LL_MODIFIER "I64"
|
||||
# elif defined(__GNUC__)
|
||||
# define TCL_WIDE_INT_TYPE long long
|
||||
# define TCL_LL_MODIFIER "ll"
|
||||
@@ -424,10 +421,6 @@ typedef TCL_WIDE_INT_TYPE Tcl_WideInt;
|
||||
typedef unsigned TCL_WIDE_INT_TYPE Tcl_WideUInt;
|
||||
|
||||
#ifdef TCL_WIDE_INT_IS_LONG
|
||||
# define Tcl_WideAsLong(val) ((long)(val))
|
||||
# define Tcl_LongAsWide(val) ((long)(val))
|
||||
# define Tcl_WideAsDouble(val) ((double)((long)(val)))
|
||||
# define Tcl_DoubleAsWide(val) ((long)((double)(val)))
|
||||
# ifndef TCL_LL_MODIFIER
|
||||
# define TCL_LL_MODIFIER "l"
|
||||
# endif /* !TCL_LL_MODIFIER */
|
||||
@@ -439,12 +432,13 @@ typedef unsigned TCL_WIDE_INT_TYPE Tcl_WideUInt;
|
||||
# ifndef TCL_LL_MODIFIER
|
||||
# define TCL_LL_MODIFIER "ll"
|
||||
# endif /* !TCL_LL_MODIFIER */
|
||||
# define Tcl_WideAsLong(val) ((long)((Tcl_WideInt)(val)))
|
||||
# define Tcl_LongAsWide(val) ((Tcl_WideInt)((long)(val)))
|
||||
# define Tcl_WideAsDouble(val) ((double)((Tcl_WideInt)(val)))
|
||||
# define Tcl_DoubleAsWide(val) ((Tcl_WideInt)((double)(val)))
|
||||
#endif /* TCL_WIDE_INT_IS_LONG */
|
||||
|
||||
#define Tcl_WideAsLong(val) ((long)((Tcl_WideInt)(val)))
|
||||
#define Tcl_LongAsWide(val) ((Tcl_WideInt)((long)(val)))
|
||||
#define Tcl_WideAsDouble(val) ((double)((Tcl_WideInt)(val)))
|
||||
#define Tcl_DoubleAsWide(val) ((Tcl_WideInt)((double)(val)))
|
||||
|
||||
#if defined(_WIN32)
|
||||
# ifdef __BORLANDC__
|
||||
typedef struct stati64 Tcl_StatBuf;
|
||||
@@ -529,7 +523,7 @@ typedef struct Tcl_Interp
|
||||
int errorLineDontUse; /* Don't use in extensions! */
|
||||
#endif
|
||||
}
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
Tcl_Interp;
|
||||
|
||||
typedef struct Tcl_AsyncHandler_ *Tcl_AsyncHandler;
|
||||
@@ -1003,7 +997,9 @@ typedef struct Tcl_DString {
|
||||
|
||||
#define Tcl_DStringLength(dsPtr) ((dsPtr)->length)
|
||||
#define Tcl_DStringValue(dsPtr) ((dsPtr)->string)
|
||||
#define Tcl_DStringTrunc Tcl_DStringSetLength
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
# define Tcl_DStringTrunc Tcl_DStringSetLength
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
* Definitions for the maximum number of digits of precision that may be
|
||||
@@ -1131,7 +1127,7 @@ typedef struct Tcl_DString {
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
# define TCL_PARSE_PART1 0x400
|
||||
#endif
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
* Types for linked variables:
|
||||
@@ -1147,8 +1143,13 @@ typedef struct Tcl_DString {
|
||||
#define TCL_LINK_SHORT 8
|
||||
#define TCL_LINK_USHORT 9
|
||||
#define TCL_LINK_UINT 10
|
||||
#if defined(TCL_WIDE_INT_IS_LONG) || defined(_WIN32) || defined(__CYGWIN__)
|
||||
#define TCL_LINK_LONG ((sizeof(long) != sizeof(int)) ? TCL_LINK_WIDE_INT : TCL_LINK_INT)
|
||||
#define TCL_LINK_ULONG ((sizeof(long) != sizeof(int)) ? TCL_LINK_WIDE_UINT : TCL_LINK_UINT)
|
||||
#else
|
||||
#define TCL_LINK_LONG 11
|
||||
#define TCL_LINK_ULONG 12
|
||||
#endif
|
||||
#define TCL_LINK_FLOAT 13
|
||||
#define TCL_LINK_WIDE_UINT 14
|
||||
#define TCL_LINK_READ_ONLY 0x80
|
||||
@@ -2534,7 +2535,7 @@ EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr);
|
||||
Tcl_DbNewBignumObj(val, __FILE__, __LINE__)
|
||||
# undef Tcl_NewBooleanObj
|
||||
# define Tcl_NewBooleanObj(val) \
|
||||
Tcl_DbNewBooleanObj(val, __FILE__, __LINE__)
|
||||
Tcl_DbNewLongObj((val)!=0, __FILE__, __LINE__)
|
||||
# undef Tcl_NewByteArrayObj
|
||||
# define Tcl_NewByteArrayObj(bytes, len) \
|
||||
Tcl_DbNewByteArrayObj(bytes, len, __FILE__, __LINE__)
|
||||
@@ -2627,7 +2628,6 @@ EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr);
|
||||
# define panic Tcl_Panic
|
||||
#endif
|
||||
# define panicVA Tcl_PanicVA
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
@@ -2638,6 +2638,8 @@ EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr);
|
||||
|
||||
extern Tcl_AppInitProc Tcl_AppInit;
|
||||
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
#endif /* RC_INVOKED */
|
||||
|
||||
/*
|
||||
|
||||
+21
-1
@@ -137,6 +137,8 @@ typedef enum TalInstType {
|
||||
* ranges */
|
||||
ASSEM_BOOL, /* One Boolean operand */
|
||||
ASSEM_BOOL_LVT4, /* One Boolean, one 4-byte LVT ref. */
|
||||
ASSEM_CLOCK_READ, /* 1-byte unsigned-integer case number, in the
|
||||
* range 0-3 */
|
||||
ASSEM_CONCAT1, /* 1-byte unsigned-integer operand count, must
|
||||
* be strictly positive, consumes N, produces
|
||||
* 1 */
|
||||
@@ -350,6 +352,7 @@ static const TalInstDesc TalInstructionTable[] = {
|
||||
{"bitnot", ASSEM_1BYTE, INST_BITNOT, 1, 1},
|
||||
{"bitor", ASSEM_1BYTE, INST_BITOR, 2, 1},
|
||||
{"bitxor", ASSEM_1BYTE, INST_BITXOR, 2, 1},
|
||||
{"clockRead", ASSEM_CLOCK_READ, INST_CLOCK_READ, 0, 1},
|
||||
{"concat", ASSEM_CONCAT1, INST_STR_CONCAT1, INT_MIN,1},
|
||||
{"concatStk", ASSEM_LIST, INST_CONCAT_STK, INT_MIN,1},
|
||||
{"coroName", ASSEM_1BYTE, INST_COROUTINE_NAME, 0, 1},
|
||||
@@ -1361,6 +1364,23 @@ AssembleOneLine(
|
||||
TclEmitInt4(localVar, envPtr);
|
||||
break;
|
||||
|
||||
case ASSEM_CLOCK_READ:
|
||||
if (parsePtr->numWords != 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, &instNameObj, "imm8");
|
||||
goto cleanup;
|
||||
}
|
||||
if (GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
if (opnd < 0 || opnd > 3) {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewStringObj("operand must be [0..3]", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "ASSEM", "OPERAND<0,>3", NULL);
|
||||
goto cleanup;
|
||||
}
|
||||
BBEmitInstInt1(assemEnvPtr, tblIdx, opnd, opnd);
|
||||
break;
|
||||
|
||||
case ASSEM_CONCAT1:
|
||||
if (parsePtr->numWords != 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, &instNameObj, "imm8");
|
||||
@@ -4246,7 +4266,7 @@ AddBasicBlockRangeToErrorInfo(
|
||||
Tcl_AppendObjToErrorInfo(interp, lineNo);
|
||||
Tcl_AddErrorInfo(interp, " and ");
|
||||
if (bbPtr->successor1 != NULL) {
|
||||
Tcl_SetIntObj(lineNo, bbPtr->successor1->startLine);
|
||||
TclSetLongObj(lineNo, bbPtr->successor1->startLine);
|
||||
Tcl_AppendObjToErrorInfo(interp, lineNo);
|
||||
} else {
|
||||
Tcl_AddErrorInfo(interp, "end of assembly code");
|
||||
|
||||
+57
-10
@@ -203,7 +203,7 @@ static const CmdInfo builtInCmds[] = {
|
||||
{"append", Tcl_AppendObjCmd, TclCompileAppendCmd, NULL, CMD_IS_SAFE},
|
||||
{"apply", Tcl_ApplyObjCmd, NULL, TclNRApplyObjCmd, CMD_IS_SAFE},
|
||||
{"break", Tcl_BreakObjCmd, TclCompileBreakCmd, NULL, CMD_IS_SAFE},
|
||||
#ifndef EXCLUDE_OBSOLETE_COMMANDS
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
{"case", Tcl_CaseObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
#endif
|
||||
{"catch", Tcl_CatchObjCmd, TclCompileCatchCmd, TclNRCatchObjCmd, CMD_IS_SAFE},
|
||||
@@ -265,7 +265,6 @@ static const CmdInfo builtInCmds[] = {
|
||||
{"cd", Tcl_CdObjCmd, NULL, NULL, 0},
|
||||
{"close", Tcl_CloseObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
{"eof", Tcl_EofObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
{"encoding", Tcl_EncodingObjCmd, NULL, NULL, 0},
|
||||
{"exec", Tcl_ExecObjCmd, NULL, NULL, 0},
|
||||
{"exit", Tcl_ExitObjCmd, NULL, NULL, 0},
|
||||
{"fblocked", Tcl_FblockedObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
@@ -511,7 +510,11 @@ Tcl_CreateInterp(void)
|
||||
iPtr = ckalloc(sizeof(Interp));
|
||||
interp = (Tcl_Interp *) iPtr;
|
||||
|
||||
#ifdef TCL_NO_DEPRECATED
|
||||
iPtr->result = &tclEmptyString;
|
||||
#else
|
||||
iPtr->result = iPtr->resultSpace;
|
||||
#endif
|
||||
iPtr->freeProc = NULL;
|
||||
iPtr->errorLine = 0;
|
||||
iPtr->objResultPtr = Tcl_NewObj();
|
||||
@@ -571,9 +574,11 @@ Tcl_CreateInterp(void)
|
||||
iPtr->rootFramePtr = NULL; /* Initialise as soon as :: is available */
|
||||
iPtr->lookupNsPtr = NULL;
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
iPtr->appendResult = NULL;
|
||||
iPtr->appendAvl = 0;
|
||||
iPtr->appendUsed = 0;
|
||||
#endif
|
||||
|
||||
Tcl_InitHashTable(&iPtr->packageTable, TCL_STRING_KEYS);
|
||||
iPtr->packageUnknown = NULL;
|
||||
@@ -603,7 +608,9 @@ Tcl_CreateInterp(void)
|
||||
iPtr->emptyObjPtr = Tcl_NewObj();
|
||||
/* Another empty object. */
|
||||
Tcl_IncrRefCount(iPtr->emptyObjPtr);
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
iPtr->resultSpace[0] = 0;
|
||||
#endif
|
||||
iPtr->threadId = Tcl_GetCurrentThread();
|
||||
|
||||
/* TIP #378 */
|
||||
@@ -790,16 +797,17 @@ Tcl_CreateInterp(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the "array", "binary", "chan", "dict", "file", "info",
|
||||
* "namespace" and "string" ensembles. Note that all these commands (and
|
||||
* their subcommands that are not present in the global namespace) are
|
||||
* wholly safe *except* for "file".
|
||||
* Create the "array", "binary", "chan", "clock", "dict", "encoding",
|
||||
* "file", "info", "namespace" and "string" ensembles. Note that all these
|
||||
* commands (and their subcommands that are not present in the global
|
||||
* namespace) are wholly safe *except* for "clock", "encoding" and "file".
|
||||
*/
|
||||
|
||||
TclInitArrayCmd(interp);
|
||||
TclInitBinaryCmd(interp);
|
||||
TclInitChanCmd(interp);
|
||||
TclInitDictCmd(interp);
|
||||
TclInitEncodingCmd(interp);
|
||||
TclInitFileCmd(interp);
|
||||
TclInitInfoCmd(interp);
|
||||
TclInitNamespaceCmd(interp);
|
||||
@@ -1027,6 +1035,7 @@ TclHideUnsafeCommands(
|
||||
Tcl_HideCommand(interp, cmdInfoPtr->name, cmdInfoPtr->name);
|
||||
}
|
||||
}
|
||||
TclMakeEncodingCommandSafe(interp); /* Ugh! */
|
||||
TclMakeFileCommandSafe(interp); /* Ugh! */
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -1062,7 +1071,7 @@ Tcl_CallWhenDeleted(
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
static Tcl_ThreadDataKey assocDataCounterKey;
|
||||
int *assocDataCounterPtr =
|
||||
Tcl_GetThreadData(&assocDataCounterKey, (int)sizeof(int));
|
||||
Tcl_GetThreadData(&assocDataCounterKey, sizeof(int));
|
||||
int isNew;
|
||||
char buffer[32 + TCL_INTEGER_SPACE];
|
||||
AssocData *dPtr = ckalloc(sizeof(AssocData));
|
||||
@@ -1534,10 +1543,12 @@ DeleteInterpProc(
|
||||
if (iPtr->returnOpts) {
|
||||
Tcl_DecrRefCount(iPtr->returnOpts);
|
||||
}
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
if (iPtr->appendResult != NULL) {
|
||||
ckfree(iPtr->appendResult);
|
||||
iPtr->appendResult = NULL;
|
||||
}
|
||||
#endif
|
||||
TclFreePackageInfo(iPtr);
|
||||
while (iPtr->tracePtr != NULL) {
|
||||
Tcl_DeleteTrace((Tcl_Interp *) iPtr, (Tcl_Trace) iPtr->tracePtr);
|
||||
@@ -4705,7 +4716,7 @@ TEOV_RunEnterTraces(
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
Command *cmdPtr = *cmdPtrPtr;
|
||||
int newEpoch, cmdEpoch = cmdPtr->cmdEpoch;
|
||||
size_t newEpoch, cmdEpoch = cmdPtr->cmdEpoch;
|
||||
int length, traceCode = TCL_OK;
|
||||
const char *command = TclGetStringFromObj(commandPtr, &length);
|
||||
|
||||
@@ -5850,6 +5861,7 @@ TclArgumentGet(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#undef Tcl_Eval
|
||||
int
|
||||
Tcl_Eval(
|
||||
@@ -5902,6 +5914,7 @@ Tcl_GlobalEvalObj(
|
||||
{
|
||||
return Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_GLOBAL);
|
||||
}
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -6055,7 +6068,7 @@ TclNREvalObjEx(
|
||||
TclNRAddCallback(interp, TEOEx_ListCallback, listPtr, eoFramePtr,
|
||||
objPtr, NULL);
|
||||
|
||||
ListObjGetElements(listPtr, objc, objv);
|
||||
TclListObjGetElements(NULL, listPtr, &objc, &objv);
|
||||
return TclNREvalObjv(interp, objc, objv, flags, NULL);
|
||||
}
|
||||
|
||||
@@ -6728,6 +6741,7 @@ Tcl_AppendObjToErrorInfo(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#undef Tcl_AddErrorInfo
|
||||
void
|
||||
Tcl_AddErrorInfo(
|
||||
@@ -6737,6 +6751,7 @@ Tcl_AddErrorInfo(
|
||||
{
|
||||
Tcl_AddObjErrorInfo(interp, message, -1);
|
||||
}
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -6909,6 +6924,7 @@ Tcl_VarEval(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#undef Tcl_GlobalEval
|
||||
int
|
||||
Tcl_GlobalEval(
|
||||
@@ -6926,6 +6942,7 @@ Tcl_GlobalEval(
|
||||
iPtr->varFramePtr = savedVarFramePtr;
|
||||
return result;
|
||||
}
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -8750,6 +8767,35 @@ TclNRCoroutineActivateCallback(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclNREvalList --
|
||||
*
|
||||
* Callback to invoke command as list, used in order to delayed
|
||||
* processing of canonical list command in sane environment.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
TclNREvalList(
|
||||
ClientData data[],
|
||||
Tcl_Interp *interp,
|
||||
int result)
|
||||
{
|
||||
int objc;
|
||||
Tcl_Obj **objv;
|
||||
Tcl_Obj *listPtr = data[0];
|
||||
|
||||
Tcl_IncrRefCount(listPtr);
|
||||
|
||||
TclMarkTailcall(interp);
|
||||
TclNRAddCallback(interp, TclNRReleaseValues, listPtr, NULL, NULL,NULL);
|
||||
TclListObjGetElements(NULL, listPtr, &objc, &objv);
|
||||
return TclNREvalObjv(interp, objc, objv, 0, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -8804,7 +8850,8 @@ NRCoroInjectObjCmd(
|
||||
*/
|
||||
|
||||
iPtr->execEnvPtr = corPtr->eePtr;
|
||||
TclNREvalObjEx(interp, Tcl_NewListObj(objc-2, objv+2), 0, NULL, INT_MIN);
|
||||
TclNRAddCallback(interp, TclNREvalList, Tcl_NewListObj(objc-2, objv+2),
|
||||
NULL, NULL, NULL);
|
||||
iPtr->execEnvPtr = savedEEPtr;
|
||||
|
||||
return TCL_OK;
|
||||
|
||||
+27
-24
@@ -89,14 +89,14 @@ static struct mem_header *allocHead = NULL; /* List of allocated structures */
|
||||
#define BODY_OFFSET \
|
||||
((size_t) (&((struct mem_header *) 0)->body))
|
||||
|
||||
static int total_mallocs = 0;
|
||||
static int total_frees = 0;
|
||||
static unsigned int total_mallocs = 0;
|
||||
static unsigned int total_frees = 0;
|
||||
static size_t current_bytes_malloced = 0;
|
||||
static size_t maximum_bytes_malloced = 0;
|
||||
static int current_malloc_packets = 0;
|
||||
static int maximum_malloc_packets = 0;
|
||||
static int break_on_malloc = 0;
|
||||
static int trace_on_at_malloc = 0;
|
||||
static unsigned int current_malloc_packets = 0;
|
||||
static unsigned int maximum_malloc_packets = 0;
|
||||
static unsigned int break_on_malloc = 0;
|
||||
static unsigned int trace_on_at_malloc = 0;
|
||||
static int alloc_tracing = FALSE;
|
||||
static int init_malloced_bodies = TRUE;
|
||||
#ifdef MEM_VALIDATE
|
||||
@@ -184,18 +184,18 @@ TclDumpMemoryInfo(
|
||||
return 0;
|
||||
}
|
||||
sprintf(buf,
|
||||
"total mallocs %10d\n"
|
||||
"total frees %10d\n"
|
||||
"current packets allocated %10d\n"
|
||||
"current bytes allocated %10lu\n"
|
||||
"maximum packets allocated %10d\n"
|
||||
"maximum bytes allocated %10lu\n",
|
||||
"total mallocs %10u\n"
|
||||
"total frees %10u\n"
|
||||
"current packets allocated %10u\n"
|
||||
"current bytes allocated %10" TCL_LL_MODIFIER "u\n"
|
||||
"maximum packets allocated %10u\n"
|
||||
"maximum bytes allocated %10" TCL_LL_MODIFIER "u\n",
|
||||
total_mallocs,
|
||||
total_frees,
|
||||
current_malloc_packets,
|
||||
(unsigned long)current_bytes_malloced,
|
||||
(Tcl_WideInt)current_bytes_malloced,
|
||||
maximum_malloc_packets,
|
||||
(unsigned long)maximum_bytes_malloced);
|
||||
(Tcl_WideInt)maximum_bytes_malloced);
|
||||
if (flags == 0) {
|
||||
fprintf((FILE *)clientData, "%s", buf);
|
||||
} else {
|
||||
@@ -359,9 +359,8 @@ Tcl_DumpActiveMemory(
|
||||
Tcl_MutexLock(ckallocMutexPtr);
|
||||
for (memScanP = allocHead; memScanP != NULL; memScanP = memScanP->flink) {
|
||||
address = &memScanP->body[0];
|
||||
fprintf(fileP, "%8" TCL_LL_MODIFIER "x - %8" TCL_LL_MODIFIER "x %7" TCL_LL_MODIFIER "d @ %s %d %s",
|
||||
(Tcl_WideInt)(size_t)address,
|
||||
(Tcl_WideInt)((size_t)address + memScanP->length - 1),
|
||||
fprintf(fileP, "%p - %p %" TCL_LL_MODIFIER "d @ %s %d %s",
|
||||
address, address + memScanP->length - 1,
|
||||
(Tcl_WideInt)memScanP->length, memScanP->file, memScanP->line,
|
||||
(memScanP->tagPtr == NULL) ? "" : memScanP->tagPtr->string);
|
||||
(void) fputc('\n', fileP);
|
||||
@@ -450,7 +449,7 @@ Tcl_DbCkalloc(
|
||||
total_mallocs++;
|
||||
if (trace_on_at_malloc && (total_mallocs >= trace_on_at_malloc)) {
|
||||
(void) fflush(stdout);
|
||||
fprintf(stderr, "reached malloc trace enable point (%d)\n",
|
||||
fprintf(stderr, "reached malloc trace enable point (%u)\n",
|
||||
total_mallocs);
|
||||
fflush(stderr);
|
||||
alloc_tracing = TRUE;
|
||||
@@ -465,7 +464,7 @@ Tcl_DbCkalloc(
|
||||
if (break_on_malloc && (total_mallocs >= break_on_malloc)) {
|
||||
break_on_malloc = 0;
|
||||
(void) fflush(stdout);
|
||||
Tcl_Panic("reached malloc break limit (%d)", total_mallocs);
|
||||
Tcl_Panic("reached malloc break limit (%u)", total_mallocs);
|
||||
}
|
||||
|
||||
current_malloc_packets++;
|
||||
@@ -848,22 +847,24 @@ MemoryCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
if (strcmp(argv[1],"break_on_malloc") == 0) {
|
||||
int value;
|
||||
if (argc != 3) {
|
||||
goto argError;
|
||||
}
|
||||
if (Tcl_GetInt(interp, argv[2], &break_on_malloc) != TCL_OK) {
|
||||
if (Tcl_GetInt(interp, argv[2], &value) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
break_on_malloc = (unsigned int) value;
|
||||
return TCL_OK;
|
||||
}
|
||||
if (strcmp(argv[1],"info") == 0) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"%-25s %10d\n%-25s %10d\n%-25s %10d\n%-25s %10lu\n%-25s %10d\n%-25s %10lu\n",
|
||||
"%-25s %10u\n%-25s %10u\n%-25s %10u\n%-25s %10" TCL_LL_MODIFIER"d\n%-25s %10u\n%-25s %10" TCL_LL_MODIFIER "d\n",
|
||||
"total mallocs", total_mallocs, "total frees", total_frees,
|
||||
"current packets allocated", current_malloc_packets,
|
||||
"current bytes allocated", (unsigned long)current_bytes_malloced,
|
||||
"current bytes allocated", (Tcl_WideInt)current_bytes_malloced,
|
||||
"maximum packets allocated", maximum_malloc_packets,
|
||||
"maximum bytes allocated", (unsigned long)maximum_bytes_malloced));
|
||||
"maximum bytes allocated", (Tcl_WideInt)maximum_bytes_malloced));
|
||||
return TCL_OK;
|
||||
}
|
||||
if (strcmp(argv[1], "init") == 0) {
|
||||
@@ -934,12 +935,14 @@ MemoryCmd(
|
||||
}
|
||||
|
||||
if (strcmp(argv[1],"trace_on_at_malloc") == 0) {
|
||||
int value;
|
||||
if (argc != 3) {
|
||||
goto argError;
|
||||
}
|
||||
if (Tcl_GetInt(interp, argv[2], &trace_on_at_malloc) != TCL_OK) {
|
||||
if (Tcl_GetInt(interp, argv[2], &value) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
trace_on_at_malloc = value;
|
||||
return TCL_OK;
|
||||
}
|
||||
if (strcmp(argv[1],"validate") == 0) {
|
||||
|
||||
+19
-5
@@ -208,11 +208,7 @@ struct ClockCommand {
|
||||
};
|
||||
|
||||
static const struct ClockCommand clockCommands[] = {
|
||||
{ "clicks", ClockClicksObjCmd },
|
||||
{ "getenv", ClockGetenvObjCmd },
|
||||
{ "microseconds", ClockMicrosecondsObjCmd },
|
||||
{ "milliseconds", ClockMillisecondsObjCmd },
|
||||
{ "seconds", ClockSecondsObjCmd },
|
||||
{ "Oldscan", TclClockOldscanObjCmd },
|
||||
{ "ConvertLocalToUTC", ClockConvertlocaltoutcObjCmd },
|
||||
{ "GetDateFields", ClockGetdatefieldsObjCmd },
|
||||
@@ -253,6 +249,19 @@ TclClockInit(
|
||||
ClockClientData *data;
|
||||
int i;
|
||||
|
||||
/* Structure of the 'clock' ensemble */
|
||||
|
||||
static const EnsembleImplMap clockImplMap[] = {
|
||||
{"add", NULL, TclCompileBasicMin1ArgCmd, NULL, NULL, 0},
|
||||
{"clicks", ClockClicksObjCmd, TclCompileClockClicksCmd, NULL, NULL, 0},
|
||||
{"format", NULL, TclCompileBasicMin1ArgCmd, NULL, NULL, 0},
|
||||
{"microseconds", ClockMicrosecondsObjCmd, TclCompileClockReadingCmd, NULL, INT2PTR(1), 0},
|
||||
{"milliseconds", ClockMillisecondsObjCmd, TclCompileClockReadingCmd, NULL, INT2PTR(2), 0},
|
||||
{"scan", NULL, TclCompileBasicMin1ArgCmd, NULL, NULL , 0},
|
||||
{"seconds", ClockSecondsObjCmd, TclCompileClockReadingCmd, NULL, INT2PTR(3), 0},
|
||||
{NULL, NULL, NULL, NULL, NULL, 0}
|
||||
};
|
||||
|
||||
/*
|
||||
* Safe interps get [::clock] as alias to a master, so do not need their
|
||||
* own copies of the support routines.
|
||||
@@ -276,6 +285,7 @@ TclClockInit(
|
||||
|
||||
/*
|
||||
* Install the commands.
|
||||
* TODO - Let Tcl_MakeEnsemble do this?
|
||||
*/
|
||||
|
||||
#define TCL_CLOCK_PREFIX_LEN 14 /* == strlen("::tcl::clock::") */
|
||||
@@ -286,6 +296,10 @@ TclClockInit(
|
||||
Tcl_CreateObjCommand(interp, cmdName, clockCmdPtr->objCmdProc, data,
|
||||
ClockDeleteCmdProc);
|
||||
}
|
||||
|
||||
/* Make the clock ensemble */
|
||||
|
||||
TclMakeEnsemble(interp, "clock", clockImplMap);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1680,7 +1694,7 @@ ThreadSafeLocalTime(
|
||||
* Get a thread-local buffer to hold the returned time.
|
||||
*/
|
||||
|
||||
struct tm *tmPtr = Tcl_GetThreadData(&tmKey, (int) sizeof(struct tm));
|
||||
struct tm *tmPtr = Tcl_GetThreadData(&tmKey, sizeof(struct tm));
|
||||
#ifdef HAVE_LOCALTIME_R
|
||||
localtime_r(timePtr, tmPtr);
|
||||
#else
|
||||
|
||||
+351
-72
@@ -46,9 +46,24 @@ struct ForeachState {
|
||||
|
||||
static int CheckAccess(Tcl_Interp *interp, Tcl_Obj *pathPtr,
|
||||
int mode);
|
||||
static int BadEncodingSubcommand(ClientData dummy,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
static int EncodingConvertfromObjCmd(ClientData dummy,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
static int EncodingConverttoObjCmd(ClientData dummy,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
static int EncodingDirsObjCmd(ClientData dummy,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
static int EncodingNamesObjCmd(ClientData dummy,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
static int EncodingSystemObjCmd(ClientData dummy,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
static inline int ForeachAssignments(Tcl_Interp *interp,
|
||||
struct ForeachState *statePtr);
|
||||
static inline void ForeachCleanup(Tcl_Interp *interp,
|
||||
@@ -149,7 +164,7 @@ Tcl_BreakObjCmd(
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
/* ARGSUSED */
|
||||
int
|
||||
Tcl_CaseObjCmd(
|
||||
@@ -267,6 +282,7 @@ Tcl_CaseObjCmd(
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -541,81 +557,282 @@ Tcl_EncodingObjCmd(
|
||||
|
||||
switch ((enum options) index) {
|
||||
case ENC_CONVERTTO:
|
||||
case ENC_CONVERTFROM: {
|
||||
Tcl_Obj *data;
|
||||
Tcl_DString ds;
|
||||
Tcl_Encoding encoding;
|
||||
int length;
|
||||
const char *stringPtr;
|
||||
|
||||
if (objc == 3) {
|
||||
encoding = Tcl_GetEncoding(interp, NULL);
|
||||
data = objv[2];
|
||||
} else if (objc == 4) {
|
||||
if (Tcl_GetEncodingFromObj(interp, objv[2], &encoding) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
data = objv[3];
|
||||
} else {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "?encoding? data");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if ((enum options) index == ENC_CONVERTFROM) {
|
||||
/*
|
||||
* Treat the string as binary data.
|
||||
*/
|
||||
|
||||
stringPtr = (char *) Tcl_GetByteArrayFromObj(data, &length);
|
||||
Tcl_ExternalToUtfDString(encoding, stringPtr, length, &ds);
|
||||
|
||||
/*
|
||||
* Note that we cannot use Tcl_DStringResult here because it will
|
||||
* truncate the string at the first null byte.
|
||||
*/
|
||||
|
||||
Tcl_SetObjResult(interp, TclDStringToObj(&ds));
|
||||
} else {
|
||||
/*
|
||||
* Store the result as binary data.
|
||||
*/
|
||||
|
||||
stringPtr = TclGetStringFromObj(data, &length);
|
||||
Tcl_UtfToExternalDString(encoding, stringPtr, length, &ds);
|
||||
Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(
|
||||
(unsigned char *) Tcl_DStringValue(&ds),
|
||||
Tcl_DStringLength(&ds)));
|
||||
Tcl_DStringFree(&ds);
|
||||
}
|
||||
|
||||
Tcl_FreeEncoding(encoding);
|
||||
break;
|
||||
}
|
||||
return EncodingConverttoObjCmd(dummy, interp, objc, objv);
|
||||
case ENC_CONVERTFROM:
|
||||
return EncodingConvertfromObjCmd(dummy, interp, objc, objv);
|
||||
case ENC_DIRS:
|
||||
return EncodingDirsObjCmd(dummy, interp, objc, objv);
|
||||
case ENC_NAMES:
|
||||
if (objc > 2) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_GetEncodingNames(interp);
|
||||
break;
|
||||
return EncodingNamesObjCmd(dummy, interp, objc, objv);
|
||||
case ENC_SYSTEM:
|
||||
if (objc > 3) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "?encoding?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (objc == 2) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
Tcl_GetEncodingName(NULL), -1));
|
||||
} else {
|
||||
return Tcl_SetSystemEncoding(interp, TclGetString(objv[2]));
|
||||
}
|
||||
break;
|
||||
return EncodingSystemObjCmd(dummy, interp, objc, objv);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* TclInitEncodingCmd --
|
||||
*
|
||||
* This function creates the 'encoding' ensemble.
|
||||
*
|
||||
* Results:
|
||||
* Returns the Tcl_Command so created.
|
||||
*
|
||||
* Side effects:
|
||||
* The ensemble is initialized.
|
||||
*
|
||||
* This command is hidden in a safe interpreter.
|
||||
*/
|
||||
|
||||
Tcl_Command
|
||||
TclInitEncodingCmd(
|
||||
Tcl_Interp* interp) /* Tcl interpreter */
|
||||
{
|
||||
static const EnsembleImplMap encodingImplMap[] = {
|
||||
{"convertfrom", EncodingConvertfromObjCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
|
||||
{"convertto", EncodingConverttoObjCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
|
||||
{"dirs", EncodingDirsObjCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
|
||||
{"names", EncodingNamesObjCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0},
|
||||
{"system", EncodingSystemObjCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
|
||||
{NULL, NULL, NULL, NULL, NULL, 0}
|
||||
};
|
||||
|
||||
return TclMakeEnsemble(interp, "encoding", encodingImplMap);
|
||||
}
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* TclMakeEncodingCommandSafe --
|
||||
*
|
||||
* This function hides the unsafe 'dirs' and 'system' subcommands of
|
||||
* the "encoding" Tcl command ensemble. It must be called only from
|
||||
* TclHideUnsafeCommands.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result
|
||||
*
|
||||
* Side effects:
|
||||
* Adds commands to the table of hidden commands.
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TclMakeEncodingCommandSafe(
|
||||
Tcl_Interp* interp) /* Tcl interpreter */
|
||||
{
|
||||
static const struct {
|
||||
const char *cmdName;
|
||||
int unsafe;
|
||||
} unsafeInfo[] = {
|
||||
{"convertfrom", 0},
|
||||
{"convertto", 0},
|
||||
{"dirs", 1},
|
||||
{"names", 0},
|
||||
{"system", 0},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
int i;
|
||||
Tcl_DString oldBuf, newBuf;
|
||||
|
||||
Tcl_DStringInit(&oldBuf);
|
||||
TclDStringAppendLiteral(&oldBuf, "::tcl::encoding::");
|
||||
Tcl_DStringInit(&newBuf);
|
||||
TclDStringAppendLiteral(&newBuf, "tcl:encoding:");
|
||||
for (i=0 ; unsafeInfo[i].cmdName != NULL ; i++) {
|
||||
if (unsafeInfo[i].unsafe) {
|
||||
const char *oldName, *newName;
|
||||
|
||||
Tcl_DStringSetLength(&oldBuf, 17);
|
||||
oldName = Tcl_DStringAppend(&oldBuf, unsafeInfo[i].cmdName, -1);
|
||||
Tcl_DStringSetLength(&newBuf, 13);
|
||||
newName = Tcl_DStringAppend(&newBuf, unsafeInfo[i].cmdName, -1);
|
||||
if (TclRenameCommand(interp, oldName, "___tmp") != TCL_OK
|
||||
|| Tcl_HideCommand(interp, "___tmp", newName) != TCL_OK) {
|
||||
Tcl_Panic("problem making 'encoding %s' safe: %s",
|
||||
unsafeInfo[i].cmdName,
|
||||
Tcl_GetString(Tcl_GetObjResult(interp)));
|
||||
}
|
||||
Tcl_CreateObjCommand(interp, oldName, BadEncodingSubcommand,
|
||||
(ClientData) unsafeInfo[i].cmdName, NULL);
|
||||
}
|
||||
}
|
||||
Tcl_DStringFree(&oldBuf);
|
||||
Tcl_DStringFree(&newBuf);
|
||||
|
||||
/*
|
||||
* Ugh. The [encoding] command is now actually safe, but it is assumed by
|
||||
* scripts that it is not, which messes up security policies.
|
||||
*/
|
||||
|
||||
if (Tcl_HideCommand(interp, "encoding", "encoding") != TCL_OK) {
|
||||
Tcl_Panic("problem making 'encoding' safe: %s",
|
||||
Tcl_GetString(Tcl_GetObjResult(interp)));
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* BadEncodingSubcommand --
|
||||
*
|
||||
* Command used to act as a backstop implementation when subcommands of
|
||||
* "encoding" are unsafe (the real implementations of the subcommands are
|
||||
* hidden). The clientData is always the full official subcommand name.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result (always a TCL_ERROR).
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
BadEncodingSubcommand(
|
||||
ClientData clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *const objv[])
|
||||
{
|
||||
const char *subcommandName = (const char *) clientData;
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"not allowed to invoke subcommand %s of encoding", subcommandName));
|
||||
Tcl_SetErrorCode(interp, "TCL", "SAFE", "SUBCOMMAND", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* EncodingConvertfromObjCmd --
|
||||
*
|
||||
* This command converts a byte array in an external encoding into a
|
||||
* Tcl string
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
EncodingConvertfromObjCmd(
|
||||
ClientData dummy, /* Not used. */
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
Tcl_Obj *data; /* Byte array to convert */
|
||||
Tcl_DString ds; /* Buffer to hold the string */
|
||||
Tcl_Encoding encoding; /* Encoding to use */
|
||||
int length; /* Length of the byte array being converted */
|
||||
const char *bytesPtr; /* Pointer to the first byte of the array */
|
||||
|
||||
if (objc == 2) {
|
||||
encoding = Tcl_GetEncoding(interp, NULL);
|
||||
data = objv[1];
|
||||
} else if (objc == 3) {
|
||||
if (Tcl_GetEncodingFromObj(interp, objv[1], &encoding) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
data = objv[2];
|
||||
} else {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?encoding? data");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the string into a byte array in 'ds'
|
||||
*/
|
||||
bytesPtr = (char *) Tcl_GetByteArrayFromObj(data, &length);
|
||||
Tcl_ExternalToUtfDString(encoding, bytesPtr, length, &ds);
|
||||
|
||||
/*
|
||||
* Note that we cannot use Tcl_DStringResult here because it will
|
||||
* truncate the string at the first null byte.
|
||||
*/
|
||||
|
||||
Tcl_SetObjResult(interp, TclDStringToObj(&ds));
|
||||
|
||||
/*
|
||||
* We're done with the encoding
|
||||
*/
|
||||
|
||||
Tcl_FreeEncoding(encoding);
|
||||
return TCL_OK;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* EncodingConverttoObjCmd --
|
||||
*
|
||||
* This command converts a Tcl string into a byte array that
|
||||
* encodes the string according to some encoding.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
EncodingConverttoObjCmd(
|
||||
ClientData dummy, /* Not used. */
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
Tcl_Obj *data; /* String to convert */
|
||||
Tcl_DString ds; /* Buffer to hold the byte array */
|
||||
Tcl_Encoding encoding; /* Encoding to use */
|
||||
int length; /* Length of the string being converted */
|
||||
const char *stringPtr; /* Pointer to the first byte of the string */
|
||||
|
||||
/* TODO - ADJUST OBJ INDICES WHEN ENSEMBLIFYING THIS */
|
||||
|
||||
if (objc == 2) {
|
||||
encoding = Tcl_GetEncoding(interp, NULL);
|
||||
data = objv[1];
|
||||
} else if (objc == 3) {
|
||||
if (Tcl_GetEncodingFromObj(interp, objv[1], &encoding) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
data = objv[2];
|
||||
} else {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?encoding? data");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the string to a byte array in 'ds'
|
||||
*/
|
||||
|
||||
stringPtr = TclGetStringFromObj(data, &length);
|
||||
Tcl_UtfToExternalDString(encoding, stringPtr, length, &ds);
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewByteArrayObj((unsigned char*) Tcl_DStringValue(&ds),
|
||||
Tcl_DStringLength(&ds)));
|
||||
Tcl_DStringFree(&ds);
|
||||
|
||||
/*
|
||||
* We're done with the encoding
|
||||
*/
|
||||
|
||||
Tcl_FreeEncoding(encoding);
|
||||
return TCL_OK;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -641,16 +858,16 @@ EncodingDirsObjCmd(
|
||||
{
|
||||
Tcl_Obj *dirListObj;
|
||||
|
||||
if (objc > 3) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "?dirList?");
|
||||
if (objc > 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?dirList?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (objc == 2) {
|
||||
if (objc == 1) {
|
||||
Tcl_SetObjResult(interp, Tcl_GetEncodingSearchPath());
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
dirListObj = objv[2];
|
||||
dirListObj = objv[1];
|
||||
if (Tcl_SetEncodingSearchPath(dirListObj) == TCL_ERROR) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"expected directory list but got \"%s\"",
|
||||
@@ -663,6 +880,68 @@ EncodingDirsObjCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* EncodingNamesObjCmd --
|
||||
*
|
||||
* This command returns a list of the available encoding names
|
||||
*
|
||||
* Results:
|
||||
* Returns a standard Tcl result
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
EncodingNamesObjCmd(ClientData dummy, /* Unused */
|
||||
Tcl_Interp* interp, /* Tcl interpreter */
|
||||
int objc, /* Number of command line args */
|
||||
Tcl_Obj* const objv[]) /* Vector of command line args */
|
||||
{
|
||||
if (objc > 1) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_GetEncodingNames(interp);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* EncodingSystemObjCmd --
|
||||
*
|
||||
* This command retrieves or changes the system encoding
|
||||
*
|
||||
* Results:
|
||||
* Returns a standard Tcl result
|
||||
*
|
||||
* Side effects:
|
||||
* May change the system encoding.
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
EncodingSystemObjCmd(ClientData dummy, /* Unused */
|
||||
Tcl_Interp* interp, /* Tcl interpreter */
|
||||
int objc, /* Number of command line args */
|
||||
Tcl_Obj* const objv[]) /* Vector of command line args */
|
||||
{
|
||||
if (objc > 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?encoding?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (objc == 1) {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewStringObj(Tcl_GetEncodingName(NULL), -1));
|
||||
} else {
|
||||
return Tcl_SetSystemEncoding(interp, TclGetString(objv[1]));
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
|
||||
+27
-3
@@ -989,8 +989,11 @@ TclNRSourceObjCmd(
|
||||
{
|
||||
const char *encodingName = NULL;
|
||||
Tcl_Obj *fileName;
|
||||
int result;
|
||||
void **pkgFiles = NULL;
|
||||
void *names = NULL;
|
||||
|
||||
if (objc != 2 && objc !=4) {
|
||||
if (objc < 2 || objc > 4) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?-encoding name? fileName");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -1008,9 +1011,30 @@ TclNRSourceObjCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
encodingName = TclGetString(objv[2]);
|
||||
}
|
||||
} else if (objc == 3) {
|
||||
/* Handle undocumented -nopkg option. This should only be
|
||||
* used by the internal ::tcl::Pkg::source utility function. */
|
||||
static const char *const nopkgoptions[] = {
|
||||
"-nopkg", NULL
|
||||
};
|
||||
int index;
|
||||
|
||||
return TclNREvalFile(interp, fileName, encodingName);
|
||||
if (TCL_ERROR == Tcl_GetIndexFromObj(interp, objv[1], nopkgoptions,
|
||||
"option", TCL_EXACT, &index)) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
pkgFiles = Tcl_GetAssocData(interp, "tclPkgFiles", NULL);
|
||||
/* Make sure that during the following TclNREvalFile no filenames
|
||||
* are recorded for inclusion in the "package files" command */
|
||||
names = *pkgFiles;
|
||||
*pkgFiles = NULL;
|
||||
}
|
||||
result = TclNREvalFile(interp, fileName, encodingName);
|
||||
if (pkgFiles) {
|
||||
/* restore "tclPkgFiles" assocdata to how it was. */
|
||||
*pkgFiles = names;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -734,6 +734,105 @@ TclCompileCatchCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
*
|
||||
* TclCompileClockClicksCmd --
|
||||
*
|
||||
* Procedure called to compile the "tcl::clock::clicks" command.
|
||||
*
|
||||
* Results:
|
||||
* Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
|
||||
* evaluation to run time.
|
||||
*
|
||||
* Side effects:
|
||||
* Instructions are added to envPtr to execute the "clock clicks"
|
||||
* command at runtime.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TclCompileClockClicksCmd(
|
||||
Tcl_Interp* interp, /* Tcl interpreter */
|
||||
Tcl_Parse *parsePtr, /* Points to a parse structure for the command
|
||||
* created by Tcl_ParseCommand. */
|
||||
Command *cmdPtr, /* Points to defintion of command being
|
||||
* compiled. */
|
||||
CompileEnv *envPtr) /* Holds resulting instructions. */
|
||||
{
|
||||
Tcl_Token* tokenPtr;
|
||||
|
||||
switch (parsePtr->numWords) {
|
||||
case 1:
|
||||
/*
|
||||
* No args
|
||||
*/
|
||||
TclEmitInstInt1(INST_CLOCK_READ, 0, envPtr);
|
||||
break;
|
||||
case 2:
|
||||
/*
|
||||
* -milliseconds or -microseconds
|
||||
*/
|
||||
tokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD
|
||||
|| tokenPtr[1].size < 4
|
||||
|| tokenPtr[1].size > 13) {
|
||||
return TCL_ERROR;
|
||||
} else if (!strncmp(tokenPtr[1].start, "-microseconds",
|
||||
tokenPtr[1].size)) {
|
||||
TclEmitInstInt1(INST_CLOCK_READ, 1, envPtr);
|
||||
break;
|
||||
} else if (!strncmp(tokenPtr[1].start, "-milliseconds",
|
||||
tokenPtr[1].size)) {
|
||||
TclEmitInstInt1(INST_CLOCK_READ, 2, envPtr);
|
||||
break;
|
||||
} else {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
default:
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
*
|
||||
* TclCompileClockReadingCmd --
|
||||
*
|
||||
* Procedure called to compile the "tcl::clock::microseconds",
|
||||
* "tcl::clock::milliseconds" and "tcl::clock::seconds" commands.
|
||||
*
|
||||
* Results:
|
||||
* Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
|
||||
* evaluation to run time.
|
||||
*
|
||||
* Side effects:
|
||||
* Instructions are added to envPtr to execute the "clock clicks"
|
||||
* command at runtime.
|
||||
*
|
||||
* Client data is 1 for microseconds, 2 for milliseconds, 3 for seconds.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TclCompileClockReadingCmd(
|
||||
Tcl_Interp* interp, /* Tcl interpreter */
|
||||
Tcl_Parse *parsePtr, /* Points to a parse structure for the command
|
||||
* created by Tcl_ParseCommand. */
|
||||
Command *cmdPtr, /* Points to defintion of command being
|
||||
* compiled. */
|
||||
CompileEnv *envPtr) /* Holds resulting instructions. */
|
||||
{
|
||||
if (parsePtr->numWords != 1) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
TclEmitInstInt1(INST_CLOCK_READ, PTR2INT(cmdPtr->objClientData), envPtr);
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
|
||||
@@ -654,6 +654,11 @@ InstructionDesc const tclInstructionTable[] = {
|
||||
/* Lappend list to general variable.
|
||||
* Stack: ... varName list => ... listVarContents */
|
||||
|
||||
{"clockRead", 2, +1, 1, {OPERAND_UINT1}},
|
||||
/* Read clock out to the stack. Operand is which clock to read
|
||||
* 0=clicks, 1=microseconds, 2=milliseconds, 3=seconds.
|
||||
* Stack: ... => ... time */
|
||||
|
||||
{NULL, 0, 0, 0, {OPERAND_NONE}}
|
||||
};
|
||||
|
||||
|
||||
@@ -425,7 +425,7 @@ typedef struct ByteCode {
|
||||
* compiled. If the code is executed if a
|
||||
* different namespace, it must be
|
||||
* recompiled. */
|
||||
int nsEpoch; /* Value of nsPtr->resolverEpoch when this
|
||||
size_t nsEpoch; /* Value of nsPtr->resolverEpoch when this
|
||||
* ByteCode was compiled. Used to invalidate
|
||||
* code when new namespace resolution rules
|
||||
* are put into effect. */
|
||||
@@ -821,8 +821,10 @@ typedef struct ByteCode {
|
||||
#define INST_LAPPEND_LIST_ARRAY_STK 187
|
||||
#define INST_LAPPEND_LIST_STK 188
|
||||
|
||||
#define INST_CLOCK_READ 189
|
||||
|
||||
/* The last opcode */
|
||||
#define LAST_INST_OPCODE 188
|
||||
#define LAST_INST_OPCODE 189
|
||||
|
||||
/*
|
||||
* Table describing the Tcl bytecode instructions: their name (for displaying
|
||||
|
||||
+47
-8
@@ -878,7 +878,7 @@ EXTERN int Tcl_EvalObjv(Tcl_Interp *interp, int objc,
|
||||
EXTERN int Tcl_EvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
int flags);
|
||||
/* 294 */
|
||||
EXTERN void Tcl_ExitThread(int status);
|
||||
EXTERN TCL_NORETURN void Tcl_ExitThread(int status);
|
||||
/* 295 */
|
||||
EXTERN int Tcl_ExternalToUtf(Tcl_Interp *interp,
|
||||
Tcl_Encoding encoding, const char *src,
|
||||
@@ -2151,7 +2151,7 @@ typedef struct TclStubs {
|
||||
int (*tcl_EvalEx) (Tcl_Interp *interp, const char *script, int numBytes, int flags); /* 291 */
|
||||
int (*tcl_EvalObjv) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); /* 292 */
|
||||
int (*tcl_EvalObjEx) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 293 */
|
||||
void (*tcl_ExitThread) (int status); /* 294 */
|
||||
TCL_NORETURN1 void (*tcl_ExitThread) (int status); /* 294 */
|
||||
int (*tcl_ExternalToUtf) (Tcl_Interp *interp, Tcl_Encoding encoding, const char *src, int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); /* 295 */
|
||||
char * (*tcl_ExternalToUtfDString) (Tcl_Encoding encoding, const char *src, int srcLen, Tcl_DString *dsPtr); /* 296 */
|
||||
void (*tcl_FinalizeThread) (void); /* 297 */
|
||||
@@ -3835,13 +3835,13 @@ extern const TclStubs *tclStubsPtr;
|
||||
sizeof(char *), msg, flags, indexPtr)
|
||||
#undef Tcl_NewBooleanObj
|
||||
#define Tcl_NewBooleanObj(boolValue) \
|
||||
Tcl_NewIntObj((boolValue)!=0)
|
||||
Tcl_NewLongObj((boolValue)!=0)
|
||||
#undef Tcl_DbNewBooleanObj
|
||||
#define Tcl_DbNewBooleanObj(boolValue, file, line) \
|
||||
Tcl_DbNewLongObj((boolValue)!=0, file, line)
|
||||
#undef Tcl_SetBooleanObj
|
||||
#define Tcl_SetBooleanObj(objPtr, boolValue) \
|
||||
Tcl_SetIntObj((objPtr), (boolValue)!=0)
|
||||
Tcl_SetLongObj(objPtr, (boolValue)!=0)
|
||||
#undef Tcl_SetVar
|
||||
#define Tcl_SetVar(interp, varName, newValue, flags) \
|
||||
Tcl_SetVar2(interp, varName, NULL, newValue, flags)
|
||||
@@ -3869,6 +3869,45 @@ extern const TclStubs *tclStubsPtr;
|
||||
#undef Tcl_AddObjErrorInfo
|
||||
#define Tcl_AddObjErrorInfo(interp, message, length) \
|
||||
Tcl_AppendObjToErrorInfo(interp, Tcl_NewStringObj(message, length))
|
||||
#ifdef TCL_NO_DEPRECATED
|
||||
#undef Tcl_Eval
|
||||
#define Tcl_Eval(interp, objPtr) \
|
||||
Tcl_EvalEx(interp, objPtr, -1, 0)
|
||||
#undef Tcl_GlobalEval
|
||||
#define Tcl_GlobalEval(interp, objPtr) \
|
||||
Tcl_EvalEx(interp, objPtr, -1, TCL_EVAL_GLOBAL)
|
||||
#undef Tcl_SaveResult
|
||||
#define Tcl_SaveResult(interp, statePtr) \
|
||||
do { \
|
||||
(statePtr)->objResultPtr = Tcl_GetObjResult(interp); \
|
||||
Tcl_IncrRefCount((statePtr)->objResultPtr); \
|
||||
Tcl_SetObjResult(interp, Tcl_NewObj()); \
|
||||
} while(0)
|
||||
#undef Tcl_RestoreResult
|
||||
#define Tcl_RestoreResult(interp, statePtr) \
|
||||
do { \
|
||||
Tcl_ResetResult(interp); \
|
||||
Tcl_SetObjResult(interp, (statePtr)->objResultPtr); \
|
||||
Tcl_DecrRefCount((statePtr)->objResultPtr); \
|
||||
} while(0)
|
||||
#undef Tcl_DiscardResult
|
||||
#define Tcl_DiscardResult(statePtr) \
|
||||
Tcl_DecrRefCount((statePtr)->objResultPtr)
|
||||
#undef Tcl_SetResult
|
||||
#define Tcl_SetResult(interp, result, freeProc) \
|
||||
do { \
|
||||
char *__result = result; \
|
||||
Tcl_FreeProc *__freeProc = freeProc; \
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(__result, -1)); \
|
||||
if (__result != NULL && __freeProc != NULL && __freeProc != TCL_VOLATILE) { \
|
||||
if (__freeProc == TCL_DYNAMIC) { \
|
||||
ckfree(__result); \
|
||||
} else { \
|
||||
(*__freeProc)(__result); \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
|
||||
#if defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS)
|
||||
# if defined(__CYGWIN__) && defined(TCL_WIDE_INT_IS_LONG)
|
||||
@@ -3923,10 +3962,10 @@ extern const TclStubs *tclStubsPtr;
|
||||
*/
|
||||
|
||||
#undef Tcl_EvalObj
|
||||
#define Tcl_EvalObj(interp,objPtr) \
|
||||
Tcl_EvalObjEx((interp),(objPtr),0)
|
||||
#define Tcl_EvalObj(interp, objPtr) \
|
||||
Tcl_EvalObjEx(interp, objPtr, 0)
|
||||
#undef Tcl_GlobalEvalObj
|
||||
#define Tcl_GlobalEvalObj(interp,objPtr) \
|
||||
Tcl_EvalObjEx((interp),(objPtr),TCL_EVAL_GLOBAL)
|
||||
#define Tcl_GlobalEvalObj(interp, objPtr) \
|
||||
Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_GLOBAL)
|
||||
|
||||
#endif /* _TCLDECLS */
|
||||
|
||||
@@ -506,7 +506,7 @@ UpdateStringOfDict(
|
||||
|
||||
/* Handle empty list case first, simplifies what follows */
|
||||
if (numElems == 0) {
|
||||
dictPtr->bytes = tclEmptyStringRep;
|
||||
dictPtr->bytes = &tclEmptyString;
|
||||
dictPtr->length = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
+20
-26
@@ -27,9 +27,8 @@ static Tcl_Obj * DisassembleByteCodeObj(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr);
|
||||
static int FormatInstruction(ByteCode *codePtr,
|
||||
const unsigned char *pc, Tcl_Obj *bufferObj);
|
||||
static void GetLocationInformation(Tcl_Interp *interp,
|
||||
Proc *procPtr, Tcl_Obj **fileObjPtr,
|
||||
int *linePtr);
|
||||
static void GetLocationInformation(Proc *procPtr,
|
||||
Tcl_Obj **fileObjPtr, int *linePtr);
|
||||
static void PrintSourceToObj(Tcl_Obj *appendObj,
|
||||
const char *stringPtr, int maxChars);
|
||||
static void UpdateStringOfInstName(Tcl_Obj *objPtr);
|
||||
@@ -73,8 +72,6 @@ static const Tcl_ObjType tclInstNameType = {
|
||||
|
||||
static void
|
||||
GetLocationInformation(
|
||||
Tcl_Interp *interp, /* Where to look up the location
|
||||
* information. */
|
||||
Proc *procPtr, /* What to look up the information for. */
|
||||
Tcl_Obj **fileObjPtr, /* Where to write the information about what
|
||||
* file the code came from. Will be written
|
||||
@@ -88,20 +85,21 @@ GetLocationInformation(
|
||||
* either with the line number or with -1 if
|
||||
* the information is not available. */
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
Tcl_HashEntry *hePtr;
|
||||
CmdFrame *cfPtr;
|
||||
CmdFrame *cfPtr = TclGetCmdFrameForProcedure(procPtr);
|
||||
|
||||
*fileObjPtr = NULL;
|
||||
*linePtr = -1;
|
||||
if (iPtr != NULL && procPtr != NULL) {
|
||||
hePtr = Tcl_FindHashEntry(iPtr->linePBodyPtr, procPtr);
|
||||
if (hePtr != NULL && (cfPtr = Tcl_GetHashValue(hePtr)) != NULL) {
|
||||
*linePtr = cfPtr->line[0];
|
||||
if (cfPtr->type == TCL_LOCATION_SOURCE) {
|
||||
*fileObjPtr = cfPtr->data.eval.path;
|
||||
}
|
||||
}
|
||||
if (cfPtr == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the source location data out of the CmdFrame.
|
||||
*/
|
||||
|
||||
*linePtr = cfPtr->line[0];
|
||||
if (cfPtr->type == TCL_LOCATION_SOURCE) {
|
||||
*fileObjPtr = cfPtr->data.eval.path;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,7 +252,6 @@ DisassembleByteCodeObj(
|
||||
int codeOffset, codeLen, srcOffset, srcLen, numCmds, delta, i, line;
|
||||
Interp *iPtr = (Interp *) *codePtr->interpHandle;
|
||||
Tcl_Obj *bufferObj, *fileObj;
|
||||
char ptrBuf1[20], ptrBuf2[20];
|
||||
|
||||
TclNewObj(bufferObj);
|
||||
if (codePtr->refCount <= 0) {
|
||||
@@ -269,16 +266,14 @@ DisassembleByteCodeObj(
|
||||
* Print header lines describing the ByteCode.
|
||||
*/
|
||||
|
||||
sprintf(ptrBuf1, "%p", codePtr);
|
||||
sprintf(ptrBuf2, "%p", iPtr);
|
||||
Tcl_AppendPrintfToObj(bufferObj,
|
||||
"ByteCode 0x%s, refCt %u, epoch %u, interp 0x%s (epoch %u)\n",
|
||||
ptrBuf1, codePtr->refCount, codePtr->compileEpoch, ptrBuf2,
|
||||
"ByteCode %p, refCt %u, epoch %u, interp %p (epoch %u)\n",
|
||||
codePtr, codePtr->refCount, codePtr->compileEpoch, iPtr,
|
||||
iPtr->compileEpoch);
|
||||
Tcl_AppendToObj(bufferObj, " Source ", -1);
|
||||
PrintSourceToObj(bufferObj, codePtr->source,
|
||||
TclMin(codePtr->numSrcBytes, 55));
|
||||
GetLocationInformation(interp, codePtr->procPtr, &fileObj, &line);
|
||||
GetLocationInformation(codePtr->procPtr, &fileObj, &line);
|
||||
if (line > -1 && fileObj != NULL) {
|
||||
Tcl_AppendPrintfToObj(bufferObj, "\n File \"%s\" Line %d",
|
||||
Tcl_GetString(fileObj), line);
|
||||
@@ -316,10 +311,9 @@ DisassembleByteCodeObj(
|
||||
Proc *procPtr = codePtr->procPtr;
|
||||
int numCompiledLocals = procPtr->numCompiledLocals;
|
||||
|
||||
sprintf(ptrBuf1, "%p", procPtr);
|
||||
Tcl_AppendPrintfToObj(bufferObj,
|
||||
" Proc 0x%s, refCt %d, args %d, compiled locals %d\n",
|
||||
ptrBuf1, procPtr->refCount, procPtr->numArgs,
|
||||
" Proc %p, refCt %d, args %d, compiled locals %d\n",
|
||||
procPtr, procPtr->refCount, procPtr->numArgs,
|
||||
numCompiledLocals);
|
||||
if (numCompiledLocals > 0) {
|
||||
CompiledLocal *localPtr = procPtr->firstLocalPtr;
|
||||
@@ -1221,7 +1215,7 @@ DisassembleByteCodeAsDicts(
|
||||
* system if it is available.
|
||||
*/
|
||||
|
||||
GetLocationInformation(interp, codePtr->procPtr, &file, &line);
|
||||
GetLocationInformation(codePtr->procPtr, &file, &line);
|
||||
|
||||
/*
|
||||
* Build the overall result.
|
||||
|
||||
@@ -92,7 +92,7 @@ static const Tcl_ObjType ensembleCmdType = {
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
int epoch; /* Used to confirm when the data in this
|
||||
size_t epoch; /* Used to confirm when the data in this
|
||||
* really structure matches up with the
|
||||
* ensemble. */
|
||||
Command *token; /* Reference to the command for which this
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ typedef struct BgError {
|
||||
* pending background errors for the interpreter.
|
||||
*/
|
||||
|
||||
typedef struct ErrAssocData {
|
||||
typedef struct {
|
||||
Tcl_Interp *interp; /* Interpreter in which error occurred. */
|
||||
Tcl_Obj *cmdPrefix; /* First word(s) of the handler command */
|
||||
BgError *firstBgPtr; /* First in list of all background errors
|
||||
|
||||
+44
-27
@@ -510,9 +510,8 @@ VarHashCreateVar(
|
||||
: (*(tPtr) = TCL_NUMBER_DOUBLE)), \
|
||||
*(ptrPtr) = (ClientData) \
|
||||
(&((objPtr)->internalRep.doubleValue)), TCL_OK) : \
|
||||
((((objPtr)->typePtr == NULL) && ((objPtr)->bytes == NULL)) || \
|
||||
(((objPtr)->bytes != NULL) && ((objPtr)->length == 0))) \
|
||||
? (*(tPtr) = TCL_NUMBER_LONG),TCL_ERROR : \
|
||||
(((objPtr)->bytes != NULL) && ((objPtr)->length == 0)) \
|
||||
? TCL_ERROR : \
|
||||
TclGetNumberFromObj((interp), (objPtr), (ptrPtr), (tPtr)))
|
||||
#else /* !TCL_WIDE_INT_IS_LONG */
|
||||
#define GetNumberFromObj(interp, objPtr, ptrPtr, tPtr) \
|
||||
@@ -530,9 +529,8 @@ VarHashCreateVar(
|
||||
: (*(tPtr) = TCL_NUMBER_DOUBLE)), \
|
||||
*(ptrPtr) = (ClientData) \
|
||||
(&((objPtr)->internalRep.doubleValue)), TCL_OK) : \
|
||||
((((objPtr)->typePtr == NULL) && ((objPtr)->bytes == NULL)) || \
|
||||
(((objPtr)->bytes != NULL) && ((objPtr)->length == 0))) \
|
||||
? (*(tPtr) = TCL_NUMBER_LONG),TCL_ERROR : \
|
||||
(((objPtr)->bytes != NULL) && ((objPtr)->length == 0)) \
|
||||
? TCL_ERROR : \
|
||||
TclGetNumberFromObj((interp), (objPtr), (ptrPtr), (tPtr)))
|
||||
#endif /* TCL_WIDE_INT_IS_LONG */
|
||||
|
||||
@@ -910,9 +908,9 @@ TclCreateExecEnv(
|
||||
+ (size_t) (size-1) * sizeof(Tcl_Obj *));
|
||||
|
||||
eePtr->execStackPtr = esPtr;
|
||||
TclNewBooleanObj(eePtr->constants[0], 0);
|
||||
TclNewLongObj(eePtr->constants[0], 0);
|
||||
Tcl_IncrRefCount(eePtr->constants[0]);
|
||||
TclNewBooleanObj(eePtr->constants[1], 1);
|
||||
TclNewLongObj(eePtr->constants[1], 1);
|
||||
Tcl_IncrRefCount(eePtr->constants[1]);
|
||||
eePtr->interp = interp;
|
||||
eePtr->callbackPtr = NULL;
|
||||
@@ -5950,16 +5948,17 @@ TEBCresume(
|
||||
value2Ptr = OBJ_AT_TOS;
|
||||
valuePtr = OBJ_UNDER_TOS;
|
||||
|
||||
if (GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK) {
|
||||
if (GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK
|
||||
|| GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2) != TCL_OK) {
|
||||
/*
|
||||
* At least one non-numeric argument - compare as strings.
|
||||
*/
|
||||
|
||||
goto stringCompare;
|
||||
}
|
||||
if (type1 == TCL_NUMBER_NAN) {
|
||||
if (type1 == TCL_NUMBER_NAN || type2 == TCL_NUMBER_NAN) {
|
||||
/*
|
||||
* NaN first arg: NaN != to everything, other compares are false.
|
||||
* NaN arg: NaN != to everything, other compares are false.
|
||||
*/
|
||||
|
||||
iResult = (*pc == INST_NEQ);
|
||||
@@ -5969,21 +5968,6 @@ TEBCresume(
|
||||
compare = MP_EQ;
|
||||
goto convertComparison;
|
||||
}
|
||||
if (GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2) != TCL_OK) {
|
||||
/*
|
||||
* At least one non-numeric argument - compare as strings.
|
||||
*/
|
||||
|
||||
goto stringCompare;
|
||||
}
|
||||
if (type2 == TCL_NUMBER_NAN) {
|
||||
/*
|
||||
* NaN 2nd arg: NaN != to everything, other compares are false.
|
||||
*/
|
||||
|
||||
iResult = (*pc == INST_NEQ);
|
||||
goto foundResult;
|
||||
}
|
||||
if ((type1 == TCL_NUMBER_LONG) && (type2 == TCL_NUMBER_LONG)) {
|
||||
l1 = *((const long *)ptr1);
|
||||
l2 = *((const long *)ptr2);
|
||||
@@ -7678,6 +7662,39 @@ TEBCresume(
|
||||
* -----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
case INST_CLOCK_READ:
|
||||
{ /* Read the wall clock */
|
||||
Tcl_WideInt wval;
|
||||
Tcl_Time now;
|
||||
switch(TclGetUInt1AtPtr(pc+1)) {
|
||||
case 0: /* clicks */
|
||||
#ifdef TCL_WIDE_CLICKS
|
||||
wval = TclpGetWideClicks();
|
||||
#else
|
||||
wval = (Tcl_WideInt) TclpGetClicks();
|
||||
#endif
|
||||
break;
|
||||
case 1: /* microseconds */
|
||||
Tcl_GetTime(&now);
|
||||
wval = (Tcl_WideInt) now.sec * 1000000 + now.usec;
|
||||
break;
|
||||
case 2: /* milliseconds */
|
||||
Tcl_GetTime(&now);
|
||||
wval = (Tcl_WideInt) now.sec * 1000 + now.usec / 1000;
|
||||
break;
|
||||
case 3: /* seconds */
|
||||
Tcl_GetTime(&now);
|
||||
wval = (Tcl_WideInt) now.sec;
|
||||
break;
|
||||
default:
|
||||
Tcl_Panic("clockRead instruction with unknown clock#");
|
||||
}
|
||||
/* TclNewWideObj(objResultPtr, wval); doesn't exist */
|
||||
objResultPtr = Tcl_NewWideIntObj(wval);
|
||||
TRACE_WITH_OBJ(("=> "), objResultPtr);
|
||||
NEXT_INST_F(2, 0, 1);
|
||||
}
|
||||
|
||||
default:
|
||||
Tcl_Panic("TclNRExecuteByteCode: unrecognized opCode %u", *pc);
|
||||
} /* end of switch on opCode */
|
||||
@@ -9213,7 +9230,7 @@ TclCompareTwoNumbers(
|
||||
Tcl_Obj *valuePtr,
|
||||
Tcl_Obj *value2Ptr)
|
||||
{
|
||||
int type1, type2, compare;
|
||||
int type1 = TCL_NUMBER_NAN, type2 = TCL_NUMBER_NAN, compare;
|
||||
ClientData ptr1, ptr2;
|
||||
mp_int big1, big2;
|
||||
double d1, d2, tmp;
|
||||
|
||||
@@ -62,15 +62,14 @@ Tcl_RecordAndEval(
|
||||
* instead of Tcl_Eval. */
|
||||
{
|
||||
register Tcl_Obj *cmdPtr;
|
||||
int length = strlen(cmd);
|
||||
int result;
|
||||
|
||||
if (length > 0) {
|
||||
if (cmd[0]) {
|
||||
/*
|
||||
* Call Tcl_RecordAndEvalObj to do the actual work.
|
||||
*/
|
||||
|
||||
cmdPtr = Tcl_NewStringObj(cmd, length);
|
||||
cmdPtr = Tcl_NewStringObj(cmd, -1);
|
||||
Tcl_IncrRefCount(cmdPtr);
|
||||
result = Tcl_RecordAndEvalObj(interp, cmdPtr, flags);
|
||||
|
||||
|
||||
+401
-373
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -214,7 +214,7 @@ typedef struct ChannelState {
|
||||
* because it happened in the background. The
|
||||
* value is the chanMg, if any. #219's
|
||||
* companion to 'unreportedError'. */
|
||||
int epoch; /* Used to test validity of stored channelname
|
||||
size_t epoch; /* Used to test validity of stored channelname
|
||||
* lookup results. */
|
||||
} ChannelState;
|
||||
|
||||
|
||||
+29
-16
@@ -25,7 +25,7 @@ typedef struct AcceptCallback {
|
||||
* It must be per-thread because of std channel limitations.
|
||||
*/
|
||||
|
||||
typedef struct ThreadSpecificData {
|
||||
typedef struct {
|
||||
int initialized; /* Set to 1 when the module is initialized. */
|
||||
Tcl_Obj *stdoutObjPtr; /* Cached stdout channel Tcl_Obj */
|
||||
} ThreadSpecificData;
|
||||
@@ -113,7 +113,6 @@ Tcl_PutsObjCmd(
|
||||
int newline; /* Add a newline at end? */
|
||||
int result; /* Result of puts operation. */
|
||||
int mode; /* Mode in which channel is opened. */
|
||||
ThreadSpecificData *tsdPtr;
|
||||
|
||||
switch (objc) {
|
||||
case 2: /* [puts $x] */
|
||||
@@ -160,7 +159,7 @@ Tcl_PutsObjCmd(
|
||||
}
|
||||
|
||||
if (chanObjPtr == NULL) {
|
||||
tsdPtr = TCL_TSD_INIT(&dataKey);
|
||||
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
|
||||
|
||||
if (!tsdPtr->initialized) {
|
||||
tsdPtr->initialized = 1;
|
||||
@@ -1618,19 +1617,34 @@ Tcl_SocketObjCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
// Set the options to their default value if the user didn't override their
|
||||
// value.
|
||||
if (reusep == -1) reusep = 0;
|
||||
if (reusea == -1) reusea = 1;
|
||||
/*
|
||||
* Set the options to their default value if the user didn't override
|
||||
* their value.
|
||||
*/
|
||||
|
||||
// Build the bitset with the flags values.
|
||||
if (reusea)
|
||||
if (reusep == -1) {
|
||||
reusep = 0;
|
||||
}
|
||||
if (reusea == -1) {
|
||||
reusea = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build the bitset with the flags values.
|
||||
*/
|
||||
|
||||
if (reusea) {
|
||||
flags |= TCL_TCPSERVER_REUSEADDR;
|
||||
if (reusep)
|
||||
}
|
||||
if (reusep) {
|
||||
flags |= TCL_TCPSERVER_REUSEPORT;
|
||||
}
|
||||
|
||||
/*
|
||||
* All the arguments should have been parsed by now, 'a' points to the
|
||||
* last one, the port number.
|
||||
*/
|
||||
|
||||
// All the arguments should have been parsed by now, 'a' points to the last
|
||||
// one, the port number.
|
||||
if (a != objc-1) {
|
||||
goto wrongNumArgs;
|
||||
}
|
||||
@@ -1638,15 +1652,14 @@ Tcl_SocketObjCmd(
|
||||
port = TclGetString(objv[a]);
|
||||
|
||||
if (server) {
|
||||
AcceptCallback *acceptCallbackPtr =
|
||||
ckalloc(sizeof(AcceptCallback));
|
||||
AcceptCallback *acceptCallbackPtr = ckalloc(sizeof(AcceptCallback));
|
||||
|
||||
Tcl_IncrRefCount(script);
|
||||
acceptCallbackPtr->script = script;
|
||||
acceptCallbackPtr->interp = interp;
|
||||
|
||||
chan = Tcl_OpenTcpServerEx(interp, port, host, flags, AcceptCallbackProc,
|
||||
acceptCallbackPtr);
|
||||
chan = Tcl_OpenTcpServerEx(interp, port, host, flags,
|
||||
AcceptCallbackProc, acceptCallbackPtr);
|
||||
if (chan == NULL) {
|
||||
Tcl_DecrRefCount(script);
|
||||
ckfree(acceptCallbackPtr);
|
||||
|
||||
+42
-25
@@ -234,7 +234,7 @@ typedef enum {
|
||||
* sharing problems.
|
||||
*/
|
||||
|
||||
typedef struct ForwardParamBase {
|
||||
typedef struct {
|
||||
int code; /* O: Ok/Fail of the cmd handler */
|
||||
char *msgStr; /* O: Error message for handler failure */
|
||||
int mustFree; /* O: True if msgStr is allocated, false if
|
||||
@@ -309,7 +309,7 @@ typedef struct ForwardingResult ForwardingResult;
|
||||
* General event structure, with reference to operation specific data.
|
||||
*/
|
||||
|
||||
typedef struct ForwardingEvent {
|
||||
typedef struct {
|
||||
Tcl_Event event; /* Basic event data, has to be first item */
|
||||
ForwardingResult *resultPtr;
|
||||
ForwardedOperation op; /* Forwarded driver operation */
|
||||
@@ -346,7 +346,7 @@ struct ForwardingResult {
|
||||
* results. */
|
||||
};
|
||||
|
||||
typedef struct ThreadSpecificData {
|
||||
typedef struct {
|
||||
/*
|
||||
* Table of all reflected channels owned by this thread. This is the
|
||||
* per-thread version of the per-interpreter map.
|
||||
@@ -723,7 +723,7 @@ TclChanCreateObjCmd(
|
||||
Tcl_DecrRefCount(rcPtr->name);
|
||||
Tcl_DecrRefCount(rcPtr->methods);
|
||||
Tcl_DecrRefCount(rcPtr->cmd);
|
||||
ckfree((char*) rcPtr);
|
||||
ckfree(rcPtr);
|
||||
return TCL_ERROR;
|
||||
|
||||
#undef MODE
|
||||
@@ -748,7 +748,7 @@ TclChanCreateObjCmd(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
typedef struct ReflectEvent {
|
||||
typedef struct {
|
||||
Tcl_Event header;
|
||||
ReflectedChannel *rcPtr;
|
||||
int events;
|
||||
@@ -851,11 +851,12 @@ TclChanPostEventObjCmd(
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that the search above subsumes several of the older checks, namely:
|
||||
* Note that the search above subsumes several of the older checks,
|
||||
* namely:
|
||||
*
|
||||
* (1) Does the channel handle refer to a reflected channel ?
|
||||
* (1) Does the channel handle refer to a reflected channel?
|
||||
* (2) Is the post event issued from the interpreter holding the handler
|
||||
* of the reflected channel ?
|
||||
* of the reflected channel?
|
||||
*
|
||||
* A successful search answers yes to both. Because the map holds only
|
||||
* handles of reflected channels, and only of such whose handler is
|
||||
@@ -939,7 +940,8 @@ TclChanPostEventObjCmd(
|
||||
|
||||
(void) GetThreadReflectedChannelMap();
|
||||
|
||||
/* XXX Race condition !!
|
||||
/*
|
||||
* XXX Race condition !!
|
||||
* XXX The destination thread may not exist anymore already.
|
||||
* XXX (Delayed postevent executed after channel got removed).
|
||||
* XXX Can we detect this ? (check the validity of the owner threadid ?)
|
||||
@@ -1221,8 +1223,8 @@ ReflectClose(
|
||||
#endif
|
||||
tctPtr = ((Channel *)rcPtr->chan)->typePtr;
|
||||
if (tctPtr && tctPtr != &tclRChannelType) {
|
||||
ckfree(tctPtr);
|
||||
((Channel *)rcPtr->chan)->typePtr = NULL;
|
||||
ckfree(tctPtr);
|
||||
((Channel *)rcPtr->chan)->typePtr = NULL;
|
||||
}
|
||||
Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
|
||||
return (result == TCL_OK) ? EOK : EINVAL;
|
||||
@@ -1272,7 +1274,10 @@ ReflectInput(
|
||||
|
||||
if (p.base.code != TCL_OK) {
|
||||
if (p.base.code < 0) {
|
||||
/* No error message, this is an errno signal. */
|
||||
/*
|
||||
* No error message, this is an errno signal.
|
||||
*/
|
||||
|
||||
*errorCodePtr = -p.base.code;
|
||||
} else {
|
||||
PassReceivedError(rcPtr->chan, &p);
|
||||
@@ -1375,7 +1380,10 @@ ReflectOutput(
|
||||
|
||||
if (p.base.code != TCL_OK) {
|
||||
if (p.base.code < 0) {
|
||||
/* No error message, this is an errno signal. */
|
||||
/*
|
||||
* No error message, this is an errno signal.
|
||||
*/
|
||||
|
||||
*errorCodePtr = -p.base.code;
|
||||
} else {
|
||||
PassReceivedError(rcPtr->chan, &p);
|
||||
@@ -1426,8 +1434,8 @@ ReflectOutput(
|
||||
|
||||
if ((written == 0) && (toWrite > 0)) {
|
||||
/*
|
||||
* The handler claims to have written nothing of what it was
|
||||
* given. That is bad.
|
||||
* The handler claims to have written nothing of what it was given.
|
||||
* That is bad.
|
||||
*/
|
||||
|
||||
SetChannelErrorStr(rcPtr->chan, msg_write_nothing);
|
||||
@@ -2373,8 +2381,8 @@ InvokeTclMethod(
|
||||
* None.
|
||||
*
|
||||
* Users:
|
||||
* ReflectInput/Output(), to enable the signaling of EAGAIN
|
||||
* on 0-sized short reads/writes.
|
||||
* ReflectInput/Output(), to enable the signaling of EAGAIN on 0-sized
|
||||
* short reads/writes.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -2560,7 +2568,10 @@ DeleteReflectedChannelMap(
|
||||
|
||||
evPtr = resultPtr->evPtr;
|
||||
|
||||
/* Basic crash safety until this routine can get revised [3411310] */
|
||||
/*
|
||||
* Basic crash safety until this routine can get revised [3411310]
|
||||
*/
|
||||
|
||||
if (evPtr == NULL) {
|
||||
continue;
|
||||
}
|
||||
@@ -2675,8 +2686,8 @@ DeleteThreadReflectedChannelMap(
|
||||
|
||||
/*
|
||||
* Go through the list of pending results and cancel all whose events were
|
||||
* destined for this thread. While this is in progress we block any
|
||||
* other access to the list of pending results.
|
||||
* destined for this thread. While this is in progress we block any other
|
||||
* access to the list of pending results.
|
||||
*/
|
||||
|
||||
Tcl_MutexLock(&rcForwardMutex);
|
||||
@@ -2707,7 +2718,10 @@ DeleteThreadReflectedChannelMap(
|
||||
|
||||
evPtr = resultPtr->evPtr;
|
||||
|
||||
/* Basic crash safety until this routine can get revised [3411310] */
|
||||
/*
|
||||
* Basic crash safety until this routine can get revised [3411310]
|
||||
*/
|
||||
|
||||
if (evPtr == NULL ) {
|
||||
continue;
|
||||
}
|
||||
@@ -2761,8 +2775,8 @@ ForwardOpToHandlerThread(
|
||||
const void *param) /* Arguments */
|
||||
{
|
||||
/*
|
||||
* Core of the communication from OWNER to HANDLER thread.
|
||||
* The receiver is ForwardProc() below.
|
||||
* Core of the communication from OWNER to HANDLER thread. The receiver is
|
||||
* ForwardProc() below.
|
||||
*/
|
||||
|
||||
Tcl_ThreadId dst = rcPtr->thread;
|
||||
@@ -2812,7 +2826,10 @@ ForwardOpToHandlerThread(
|
||||
*/
|
||||
|
||||
TclSpliceIn(resultPtr, forwardList);
|
||||
/* Do not unlock here. That is done by the ConditionWait */
|
||||
|
||||
/*
|
||||
* Do not unlock here. That is done by the ConditionWait.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Ensure cleanup of the event if the origin thread exits while this event
|
||||
@@ -2888,7 +2905,7 @@ ForwardProc(
|
||||
* Notes regarding access to the referenced data.
|
||||
*
|
||||
* In principle the data belongs to the originating thread (see
|
||||
* evPtr->src), however this thread is currently blocked at (*), i.e.
|
||||
* evPtr->src), however this thread is currently blocked at (*), i.e.,
|
||||
* quiescent. Because of this we can treat the data as belonging to us,
|
||||
* without fear of race conditions. I.e. we can read and write as we like.
|
||||
*
|
||||
|
||||
@@ -329,7 +329,7 @@ struct ForwardingResult {
|
||||
* results. */
|
||||
};
|
||||
|
||||
typedef struct ThreadSpecificData {
|
||||
typedef struct {
|
||||
/*
|
||||
* Table of all reflected transformations owned by this thread.
|
||||
*/
|
||||
|
||||
+19
-10
@@ -12,16 +12,21 @@
|
||||
#include "tclInt.h"
|
||||
|
||||
#if defined(_WIN32) && defined(UNICODE)
|
||||
/* On Windows, we need to do proper Unicode->UTF-8 conversion. */
|
||||
/*
|
||||
* On Windows, we need to do proper Unicode->UTF-8 conversion.
|
||||
*/
|
||||
|
||||
typedef struct ThreadSpecificData {
|
||||
typedef struct {
|
||||
int initialized;
|
||||
Tcl_DString errorMsg; /* UTF-8 encoded error-message */
|
||||
} ThreadSpecificData;
|
||||
static Tcl_ThreadDataKey dataKey;
|
||||
|
||||
#undef gai_strerror
|
||||
static const char *gai_strerror(int code) {
|
||||
static const char *
|
||||
gai_strerror(
|
||||
int code)
|
||||
{
|
||||
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
|
||||
|
||||
if (tsdPtr->initialized) {
|
||||
@@ -126,7 +131,7 @@ TclSockMinimumBuffers(
|
||||
}
|
||||
len = sizeof(int);
|
||||
getsockopt((SOCKET)(size_t) sock, SOL_SOCKET, SO_RCVBUF,
|
||||
(char *) ¤t, &len);
|
||||
(char *) ¤t, &len);
|
||||
if (current < size) {
|
||||
len = sizeof(int);
|
||||
setsockopt((SOCKET)(size_t) sock, SOL_SOCKET, SO_RCVBUF,
|
||||
@@ -215,7 +220,7 @@ TclCreateSocketAddress(
|
||||
* We found some problems when using AI_ADDRCONFIG, e.g. on systems that
|
||||
* have no networking besides the loopback interface and want to resolve
|
||||
* localhost. See [Bugs 3385024, 3382419, 3382431]. As the advantage of
|
||||
* using AI_ADDRCONFIG in situations where it works, is probably low,
|
||||
* using AI_ADDRCONFIG is probably low even in situations where it works,
|
||||
* we'll leave it out for now. After all, it is just an optimisation.
|
||||
*
|
||||
* Missing on: OpenBSD, NetBSD.
|
||||
@@ -300,16 +305,20 @@ TclCreateSocketAddress(
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
Tcl_Channel Tcl_OpenTcpServer(Tcl_Interp *interp, int port,
|
||||
const char *host, Tcl_TcpAcceptProc *acceptProc,
|
||||
ClientData callbackData)
|
||||
|
||||
Tcl_Channel
|
||||
Tcl_OpenTcpServer(
|
||||
Tcl_Interp *interp,
|
||||
int port,
|
||||
const char *host,
|
||||
Tcl_TcpAcceptProc *acceptProc,
|
||||
ClientData callbackData)
|
||||
{
|
||||
char portbuf[TCL_INTEGER_SPACE];
|
||||
|
||||
TclFormatInt(portbuf, port);
|
||||
|
||||
return Tcl_OpenTcpServerEx(interp, portbuf, host, TCL_TCPSERVER_REUSEADDR,
|
||||
acceptProc, callbackData);
|
||||
acceptProc, callbackData);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+30
-23
@@ -57,7 +57,7 @@ typedef struct FilesystemRecord {
|
||||
* this information each time the corresponding epoch counter changes.
|
||||
*/
|
||||
|
||||
typedef struct ThreadSpecificData {
|
||||
typedef struct {
|
||||
int initialized;
|
||||
size_t cwdPathEpoch;
|
||||
size_t filesystemEpoch;
|
||||
@@ -611,6 +611,7 @@ FsRecacheFilesystemList(void)
|
||||
|
||||
while (toFree) {
|
||||
FilesystemRecord *next = toFree->nextPtr;
|
||||
|
||||
toFree->fsPtr = NULL;
|
||||
ckfree(toFree);
|
||||
toFree = next;
|
||||
@@ -672,7 +673,6 @@ TclFSEpoch(void)
|
||||
|
||||
return tsdPtr->filesystemEpoch;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If non-NULL, clientData is owned by us and must be freed later.
|
||||
@@ -784,7 +784,9 @@ TclFinalizeFilesystem(void)
|
||||
while (fsRecPtr != NULL) {
|
||||
FilesystemRecord *tmpFsRecPtr = fsRecPtr->nextPtr;
|
||||
|
||||
/* The native filesystem is static, so we don't free it. */
|
||||
/*
|
||||
* The native filesystem is static, so we don't free it.
|
||||
*/
|
||||
|
||||
if (fsRecPtr != &nativeFilesystemRecord) {
|
||||
ckfree(fsRecPtr);
|
||||
@@ -947,7 +949,7 @@ Tcl_FSRegister(
|
||||
|
||||
int
|
||||
Tcl_FSUnregister(
|
||||
const Tcl_Filesystem *fsPtr) /* The filesystem record to remove. */
|
||||
const Tcl_Filesystem *fsPtr)/* The filesystem record to remove. */
|
||||
{
|
||||
int retVal = TCL_ERROR;
|
||||
FilesystemRecord *fsRecPtr;
|
||||
@@ -1233,7 +1235,7 @@ FsAddMountsToGlobResult(
|
||||
|
||||
len--;
|
||||
}
|
||||
len++; /* account for '/' in the mElt [Bug 1602539] */
|
||||
len++; /* account for '/' in the mElt [Bug 1602539] */
|
||||
mElt = TclNewFSPathObj(pathPtr, mount + len, mlen - len);
|
||||
Tcl_ListObjAppendElement(NULL, resultPtr, mElt);
|
||||
}
|
||||
@@ -1403,7 +1405,7 @@ TclFSNormalizeToUniquePath(
|
||||
* Call each of the "normalise path" functions in succession. This is a
|
||||
* special case, in which if we have a native filesystem handler, we call
|
||||
* it first. This is because the root of Tcl's filesystem is always a
|
||||
* native filesystem (i.e. '/' on unix is native).
|
||||
* native filesystem (i.e., '/' on unix is native).
|
||||
*/
|
||||
|
||||
firstFsRecPtr = FsGetFirstFilesystem();
|
||||
@@ -1525,7 +1527,7 @@ TclGetOpenModeEx(
|
||||
#define RW_MODES (O_RDONLY|O_WRONLY|O_RDWR)
|
||||
|
||||
/*
|
||||
* Check for the simpler fopen-like access modes (e.g. "r"). They are
|
||||
* Check for the simpler fopen-like access modes (e.g., "r"). They are
|
||||
* distinguished from the POSIX access modes by the presence of a
|
||||
* lower-case first letter.
|
||||
*/
|
||||
@@ -2671,6 +2673,7 @@ Tcl_FSGetCwd(
|
||||
fsRecPtr = fsRecPtr->nextPtr) {
|
||||
ClientData retCd;
|
||||
TclFSGetCwdProc2 *proc2;
|
||||
|
||||
if (fsRecPtr->fsPtr->getCwdProc == NULL) {
|
||||
continue;
|
||||
}
|
||||
@@ -3143,8 +3146,8 @@ Tcl_FSLoadFile(
|
||||
* Workaround for issue with modern HPUX which do allow the unlink (no ETXTBSY
|
||||
* error) yet somehow trash some internal data structures which prevents the
|
||||
* second and further shared libraries from getting properly loaded. Only the
|
||||
* first is ok. We try to get around the issue by not unlinking,
|
||||
* i.e. emulating the behaviour of the older HPUX which denied removal.
|
||||
* first is ok. We try to get around the issue by not unlinking, i.e.,
|
||||
* emulating the behaviour of the older HPUX which denied removal.
|
||||
*
|
||||
* Doing the unlink is also an issue within docker containers, whose AUFS
|
||||
* bungles this as well, see
|
||||
@@ -3162,28 +3165,30 @@ Tcl_FSLoadFile(
|
||||
*/
|
||||
|
||||
int
|
||||
TclSkipUnlink (Tcl_Obj* shlibFile)
|
||||
TclSkipUnlink(
|
||||
Tcl_Obj *shlibFile)
|
||||
{
|
||||
/* Order of testing:
|
||||
/*
|
||||
* Order of testing:
|
||||
* 1. On hpux we generally want to skip unlink in general
|
||||
*
|
||||
* Outside of hpux then:
|
||||
* 2. For a general user request (TCL_TEMPLOAD_NO_UNLINK present, non-empty, => int)
|
||||
* 2. For a general user request (TCL_TEMPLOAD_NO_UNLINK present,
|
||||
* non-empty, => int)
|
||||
* 3. For general AUFS environment (statfs, if available).
|
||||
*
|
||||
* Ad 2: This variable can disable/override the AUFS detection, i.e. for
|
||||
* testing if a newer AUFS does not have the bug any more.
|
||||
* testing if a newer AUFS does not have the bug any more.
|
||||
*
|
||||
* Ad 3: This is conditionally compiled in. Condition currently must be set manually.
|
||||
* This part needs proper tests in the configure(.in).
|
||||
* Ad 3: This is conditionally compiled in. Condition currently must be
|
||||
* set manually. This part needs proper tests in the configure(.in).
|
||||
*/
|
||||
|
||||
#ifdef hpux
|
||||
return 1;
|
||||
#else
|
||||
char* skipstr;
|
||||
char *skipstr = getenv("TCL_TEMPLOAD_NO_UNLINK");
|
||||
|
||||
skipstr = getenv ("TCL_TEMPLOAD_NO_UNLINK");
|
||||
if (skipstr && (skipstr[0] != '\0')) {
|
||||
return atoi(skipstr);
|
||||
}
|
||||
@@ -3192,7 +3197,8 @@ TclSkipUnlink (Tcl_Obj* shlibFile)
|
||||
#ifndef NO_FSTATFS
|
||||
{
|
||||
struct statfs fs;
|
||||
/* Have fstatfs. May not have the AUFS super magic ... Indeed our build
|
||||
/*
|
||||
* Have fstatfs. May not have the AUFS super magic ... Indeed our build
|
||||
* box is too old to have it directly in the headers. Define taken from
|
||||
* http://mooon.googlecode.com/svn/trunk/linux_include/linux/aufs_type.h
|
||||
* http://aufs.sourceforge.net/
|
||||
@@ -3209,8 +3215,10 @@ TclSkipUnlink (Tcl_Obj* shlibFile)
|
||||
#endif /* ... NO_FSTATFS */
|
||||
#endif /* ... TCL_TEMPLOAD_NO_UNLINK */
|
||||
|
||||
/* Fallback: !hpux, no EV override, no AUFS (detection, nor detected):
|
||||
* Don't skip */
|
||||
/*
|
||||
* Fallback: !hpux, no EV override, no AUFS (detection, nor detected):
|
||||
* Don't skip
|
||||
*/
|
||||
return 0;
|
||||
#endif /* hpux */
|
||||
}
|
||||
@@ -3415,9 +3423,8 @@ Tcl_LoadFile(
|
||||
* avoids any worries about leaving the copy laying around on exit.
|
||||
*/
|
||||
|
||||
if (
|
||||
!TclSkipUnlink (copyToPtr) &&
|
||||
(Tcl_FSDeleteFile(copyToPtr) == TCL_OK)) {
|
||||
if (!TclSkipUnlink(copyToPtr) &&
|
||||
(Tcl_FSDeleteFile(copyToPtr) == TCL_OK)) {
|
||||
Tcl_DecrRefCount(copyToPtr);
|
||||
|
||||
/*
|
||||
|
||||
@@ -101,6 +101,7 @@ typedef struct {
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#undef Tcl_GetIndexFromObj
|
||||
int
|
||||
Tcl_GetIndexFromObj(
|
||||
@@ -137,6 +138,7 @@ Tcl_GetIndexFromObj(
|
||||
return Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, sizeof(char *),
|
||||
msg, flags, indexPtr);
|
||||
}
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
|
||||
+36
-46
@@ -265,7 +265,7 @@ typedef struct Namespace {
|
||||
* strings; values have type (Namespace *). If
|
||||
* NULL, there are no children. */
|
||||
#endif
|
||||
long nsId; /* Unique id for the namespace. */
|
||||
size_t nsId; /* Unique id for the namespace. */
|
||||
Tcl_Interp *interp; /* The interpreter containing this
|
||||
* namespace. */
|
||||
int flags; /* OR-ed combination of the namespace status
|
||||
@@ -299,12 +299,12 @@ typedef struct Namespace {
|
||||
* registered using "namespace export". */
|
||||
int maxExportPatterns; /* Mumber of export patterns for which space
|
||||
* is currently allocated. */
|
||||
int cmdRefEpoch; /* Incremented if a newly added command
|
||||
size_t cmdRefEpoch; /* Incremented if a newly added command
|
||||
* shadows a command for which this namespace
|
||||
* has already cached a Command* pointer; this
|
||||
* causes all its cached Command* pointers to
|
||||
* be invalidated. */
|
||||
int resolverEpoch; /* Incremented whenever (a) the name
|
||||
size_t resolverEpoch; /* Incremented whenever (a) the name
|
||||
* resolution rules change for this namespace
|
||||
* or (b) a newly added command shadows a
|
||||
* command that is compiled to bytecodes. This
|
||||
@@ -331,7 +331,7 @@ typedef struct Namespace {
|
||||
* LookupCompiledLocal to resolve variable
|
||||
* references within the namespace at compile
|
||||
* time. */
|
||||
int exportLookupEpoch; /* Incremented whenever a command is added to
|
||||
size_t exportLookupEpoch; /* Incremented whenever a command is added to
|
||||
* a namespace, removed from a namespace or
|
||||
* the exports of a namespace are changed.
|
||||
* Allows TIP#112-driven command lists to be
|
||||
@@ -432,7 +432,7 @@ typedef struct EnsembleConfig {
|
||||
* if the command has been deleted (or never
|
||||
* existed; the global namespace never has an
|
||||
* ensemble command.) */
|
||||
int epoch; /* The epoch at which this ensemble's table of
|
||||
size_t epoch; /* The epoch at which this ensemble's table of
|
||||
* exported commands is valid. */
|
||||
char **subcommandArrayPtr; /* Array of ensemble subcommand names. At all
|
||||
* consistent points, this will have the same
|
||||
@@ -1357,7 +1357,7 @@ MODULE_SCOPE void TclThreadDataKeySet(Tcl_ThreadDataKey *keyPtr,
|
||||
*/
|
||||
|
||||
#define TCL_TSD_INIT(keyPtr) \
|
||||
(ThreadSpecificData *)Tcl_GetThreadData((keyPtr), sizeof(ThreadSpecificData))
|
||||
Tcl_GetThreadData((keyPtr), sizeof(ThreadSpecificData))
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------
|
||||
@@ -1639,7 +1639,7 @@ typedef struct Command {
|
||||
* representing a command's name in a ByteCode
|
||||
* instruction sequence. This structure can be
|
||||
* freed when refCount becomes zero. */
|
||||
int cmdEpoch; /* Incremented to invalidate any references
|
||||
size_t cmdEpoch; /* Incremented to invalidate any references
|
||||
* that point to this command when it is
|
||||
* renamed, deleted, hidden, or exposed. */
|
||||
CompileProc *compileProc; /* Procedure called to compile command. NULL
|
||||
@@ -1862,6 +1862,7 @@ typedef struct Interp {
|
||||
* See Tcl_AppendResult code for details.
|
||||
*/
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
char *appendResult; /* Storage space for results generated by
|
||||
* Tcl_AppendResult. Ckalloc-ed. NULL means
|
||||
* not yet allocated. */
|
||||
@@ -1869,6 +1870,11 @@ typedef struct Interp {
|
||||
* partialResult. */
|
||||
int appendUsed; /* Number of non-null bytes currently stored
|
||||
* at partialResult. */
|
||||
#else
|
||||
char *appendResultDontUse;
|
||||
int appendAvlDontUse;
|
||||
int appendUsedDontUse;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Information about packages. Used only in tclPkg.c.
|
||||
@@ -1930,8 +1936,12 @@ typedef struct Interp {
|
||||
* string. Returned by Tcl_ObjSetVar2 when
|
||||
* variable traces change a variable in a
|
||||
* gross way. */
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
char resultSpace[TCL_RESULT_SIZE+1];
|
||||
/* Static space holding small results. */
|
||||
#else
|
||||
char resultSpaceDontUse[TCL_RESULT_SIZE+1];
|
||||
#endif
|
||||
Tcl_Obj *objResultPtr; /* If the last command returned an object
|
||||
* result, this points to it. Should not be
|
||||
* accessed directly; see comment above. */
|
||||
@@ -2620,7 +2630,7 @@ typedef void (TclInitProcessGlobalValueProc)(char **valuePtr, size_t *lengthPtr,
|
||||
*/
|
||||
|
||||
typedef struct ProcessGlobalValue {
|
||||
size_t epoch; /* Epoch counter to detect changes in the
|
||||
size_t epoch; /* Epoch counter to detect changes in the
|
||||
* master value. */
|
||||
size_t numBytes; /* Length of the master string. */
|
||||
char *value; /* The master string value. */
|
||||
@@ -2745,7 +2755,6 @@ MODULE_SCOPE long tclObjsShared[TCL_MAX_SHARED_OBJ_STATS];
|
||||
* shared by all new objects allocated by Tcl_NewObj.
|
||||
*/
|
||||
|
||||
MODULE_SCOPE char * tclEmptyStringRep;
|
||||
MODULE_SCOPE char tclEmptyString;
|
||||
|
||||
/*
|
||||
@@ -2962,7 +2971,8 @@ MODULE_SCOPE Tcl_Obj * TclGetBgErrorHandler(Tcl_Interp *interp);
|
||||
MODULE_SCOPE int TclGetChannelFromObj(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr, Tcl_Channel *chanPtr,
|
||||
int *modePtr, int flags);
|
||||
MODULE_SCOPE int TclGetCompletionCodeFromObj(Tcl_Interp *interp,
|
||||
MODULE_SCOPE CmdFrame * TclGetCmdFrameForProcedure(Proc *procPtr);
|
||||
MODULE_SCOPE int TclGetCompletionCodeFromObj(Tcl_Interp *interp,
|
||||
Tcl_Obj *value, int *code);
|
||||
MODULE_SCOPE int TclGetNumberFromObj(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr, ClientData *clientDataPtr,
|
||||
@@ -3115,7 +3125,7 @@ MODULE_SCOPE void TclpSetVariables(Tcl_Interp *interp);
|
||||
MODULE_SCOPE void * TclThreadStorageKeyGet(Tcl_ThreadDataKey *keyPtr);
|
||||
MODULE_SCOPE void TclThreadStorageKeySet(Tcl_ThreadDataKey *keyPtr,
|
||||
void *data);
|
||||
MODULE_SCOPE void TclpThreadExit(int status);
|
||||
MODULE_SCOPE TCL_NORETURN void TclpThreadExit(int status);
|
||||
MODULE_SCOPE void TclRememberCondition(Tcl_Condition *mutex);
|
||||
MODULE_SCOPE void TclRememberJoinableThread(Tcl_ThreadId id);
|
||||
MODULE_SCOPE void TclRememberMutex(Tcl_Mutex *mutex);
|
||||
@@ -3219,9 +3229,11 @@ MODULE_SCOPE Tcl_Command TclInitBinaryCmd(Tcl_Interp *interp);
|
||||
MODULE_SCOPE int Tcl_BreakObjCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
MODULE_SCOPE int Tcl_CaseObjCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
#endif
|
||||
MODULE_SCOPE int Tcl_CatchObjCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
@@ -3276,10 +3288,8 @@ MODULE_SCOPE int Tcl_AssembleObjCmd(ClientData clientData,
|
||||
MODULE_SCOPE int TclNRAssembleObjCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
|
||||
MODULE_SCOPE int Tcl_EncodingObjCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
MODULE_SCOPE Tcl_Command TclInitEncodingCmd(Tcl_Interp *interp);
|
||||
MODULE_SCOPE int TclMakeEncodingCommandSafe(Tcl_Interp *interp);
|
||||
MODULE_SCOPE int Tcl_EofObjCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
@@ -3517,6 +3527,12 @@ MODULE_SCOPE int TclCompileBreakCmd(Tcl_Interp *interp,
|
||||
MODULE_SCOPE int TclCompileCatchCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileClockClicksCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileClockReadingCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileConcatCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
@@ -3953,7 +3969,7 @@ MODULE_SCOPE int TclCompileAssembleCmd(Tcl_Interp *interp,
|
||||
struct CompileEnv *envPtr);
|
||||
|
||||
/*
|
||||
* Functions defined in generic/tclVar.c and currenttly exported only for use
|
||||
* Functions defined in generic/tclVar.c and currently exported only for use
|
||||
* by the bytecode compiler and engine. Some of these could later be placed in
|
||||
* the public interface.
|
||||
*/
|
||||
@@ -4064,7 +4080,7 @@ typedef const char *TclDTraceStr;
|
||||
TclIncrObjsAllocated(); \
|
||||
TclAllocObjStorage(objPtr); \
|
||||
(objPtr)->refCount = 0; \
|
||||
(objPtr)->bytes = tclEmptyStringRep; \
|
||||
(objPtr)->bytes = &tclEmptyString; \
|
||||
(objPtr)->length = 0; \
|
||||
(objPtr)->typePtr = NULL; \
|
||||
TCL_DTRACE_OBJ_CREATE(objPtr)
|
||||
@@ -4081,7 +4097,7 @@ typedef const char *TclDTraceStr;
|
||||
if (!(objPtr)->typePtr || !(objPtr)->typePtr->freeIntRepProc) { \
|
||||
TCL_DTRACE_OBJ_FREE(objPtr); \
|
||||
if ((objPtr)->bytes \
|
||||
&& ((objPtr)->bytes != tclEmptyStringRep)) { \
|
||||
&& ((objPtr)->bytes != &tclEmptyString)) { \
|
||||
ckfree((objPtr)->bytes); \
|
||||
} \
|
||||
(objPtr)->length = -1; \
|
||||
@@ -4242,7 +4258,7 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
|
||||
|
||||
#define TclInitStringRep(objPtr, bytePtr, len) \
|
||||
if ((len) == 0) { \
|
||||
(objPtr)->bytes = tclEmptyStringRep; \
|
||||
(objPtr)->bytes = &tclEmptyString; \
|
||||
(objPtr)->length = 0; \
|
||||
} else { \
|
||||
(objPtr)->bytes = (char *) ckalloc((unsigned) ((len) + 1)); \
|
||||
@@ -4300,7 +4316,7 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
|
||||
|
||||
#define TclInvalidateStringRep(objPtr) \
|
||||
if ((objPtr)->bytes != NULL) { \
|
||||
if ((objPtr)->bytes != tclEmptyStringRep) { \
|
||||
if ((objPtr)->bytes != &tclEmptyString) { \
|
||||
ckfree((objPtr)->bytes); \
|
||||
} \
|
||||
(objPtr)->bytes = NULL; \
|
||||
@@ -4515,9 +4531,7 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit;
|
||||
* core. They should only be called on unshared objects. The ANSI C
|
||||
* "prototypes" for these macros are:
|
||||
*
|
||||
* MODULE_SCOPE void TclSetIntObj(Tcl_Obj *objPtr, int intValue);
|
||||
* MODULE_SCOPE void TclSetLongObj(Tcl_Obj *objPtr, long longValue);
|
||||
* MODULE_SCOPE void TclSetBooleanObj(Tcl_Obj *objPtr, long boolValue);
|
||||
* MODULE_SCOPE void TclSetWideIntObj(Tcl_Obj *objPtr, Tcl_WideInt w);
|
||||
* MODULE_SCOPE void TclSetDoubleObj(Tcl_Obj *objPtr, double d);
|
||||
*----------------------------------------------------------------
|
||||
@@ -4531,19 +4545,6 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit;
|
||||
(objPtr)->typePtr = &tclIntType; \
|
||||
} while (0)
|
||||
|
||||
#define TclSetIntObj(objPtr, l) \
|
||||
TclSetLongObj(objPtr, l)
|
||||
|
||||
/*
|
||||
* NOTE: There is to be no such thing as a "pure" boolean. Boolean values set
|
||||
* programmatically go straight to being "int" Tcl_Obj's, with value 0 or 1.
|
||||
* The only "boolean" Tcl_Obj's shall be those holding the cached boolean
|
||||
* value of strings like: "yes", "no", "true", "false", "on", "off".
|
||||
*/
|
||||
|
||||
#define TclSetBooleanObj(objPtr, b) \
|
||||
TclSetLongObj(objPtr, (b)!=0);
|
||||
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
#define TclSetWideIntObj(objPtr, w) \
|
||||
do { \
|
||||
@@ -4569,7 +4570,6 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit;
|
||||
* the core. The ANSI C "prototypes" for these macros are:
|
||||
*
|
||||
* MODULE_SCOPE void TclNewLongObj(Tcl_Obj *objPtr, long l);
|
||||
* MODULE_SCOPE void TclNewBooleanObj(Tcl_Obj *objPtr, int b);
|
||||
* MODULE_SCOPE void TclNewWideObj(Tcl_Obj *objPtr, Tcl_WideInt w);
|
||||
* MODULE_SCOPE void TclNewDoubleObj(Tcl_Obj *objPtr, double d);
|
||||
* MODULE_SCOPE void TclNewStringObj(Tcl_Obj *objPtr, const char *s, int len);
|
||||
@@ -4590,13 +4590,6 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit;
|
||||
TCL_DTRACE_OBJ_CREATE(objPtr); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* NOTE: There is to be no such thing as a "pure" boolean.
|
||||
* See comment above TclSetBooleanObj macro above.
|
||||
*/
|
||||
#define TclNewBooleanObj(objPtr, b) \
|
||||
TclNewLongObj((objPtr), (b)!=0)
|
||||
|
||||
#define TclNewDoubleObj(objPtr, d) \
|
||||
do { \
|
||||
TclIncrObjsAllocated(); \
|
||||
@@ -4622,9 +4615,6 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit;
|
||||
#define TclNewLongObj(objPtr, l) \
|
||||
(objPtr) = Tcl_NewLongObj(l)
|
||||
|
||||
#define TclNewBooleanObj(objPtr, b) \
|
||||
(objPtr) = Tcl_NewBooleanObj(b)
|
||||
|
||||
#define TclNewDoubleObj(objPtr, d) \
|
||||
(objPtr) = Tcl_NewDoubleObj(d)
|
||||
|
||||
|
||||
@@ -3533,9 +3533,6 @@ Tcl_LimitAddHandler(
|
||||
if (deleteProc == (Tcl_LimitHandlerDeleteProc *) TCL_DYNAMIC) {
|
||||
deleteProc = (Tcl_LimitHandlerDeleteProc *) Tcl_Free;
|
||||
}
|
||||
if (deleteProc == (Tcl_LimitHandlerDeleteProc *) TCL_STATIC) {
|
||||
deleteProc = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a handler record.
|
||||
|
||||
+127
-144
@@ -36,8 +36,10 @@ typedef struct Link {
|
||||
unsigned int ui;
|
||||
short s;
|
||||
unsigned short us;
|
||||
#if !defined(TCL_WIDE_INT_IS_LONG) && !defined(_WIN32) && !defined(__CYGWIN__)
|
||||
long l;
|
||||
unsigned long ul;
|
||||
#endif
|
||||
Tcl_WideInt w;
|
||||
Tcl_WideUInt uw;
|
||||
float f;
|
||||
@@ -67,10 +69,9 @@ typedef struct Link {
|
||||
static char * LinkTraceProc(ClientData clientData,Tcl_Interp *interp,
|
||||
const char *name1, const char *name2, int flags);
|
||||
static Tcl_Obj * ObjValue(Link *linkPtr);
|
||||
static int GetInvalidIntFromObj(Tcl_Obj *objPtr,
|
||||
int *intPtr);
|
||||
static int GetInvalidDoubleFromObj(Tcl_Obj *objPtr,
|
||||
double *doublePtr);
|
||||
static int GetInvalidIntFromObj(Tcl_Obj *objPtr, int *intPtr);
|
||||
static int GetInvalidWideFromObj(Tcl_Obj *objPtr, Tcl_WideInt *widePtr);
|
||||
static int GetInvalidDoubleFromObj(Tcl_Obj *objPtr, double *doublePtr);
|
||||
|
||||
/*
|
||||
* Convenience macro for accessing the value of the C variable pointed to by a
|
||||
@@ -130,6 +131,14 @@ Tcl_LinkVar(
|
||||
Tcl_IncrRefCount(linkPtr->varName);
|
||||
linkPtr->addr = addr;
|
||||
linkPtr->type = type & ~TCL_LINK_READ_ONLY;
|
||||
#if !defined(TCL_NO_DEPRECATED) && (defined(TCL_WIDE_INT_IS_LONG) \
|
||||
|| defined(_WIN32) || defined(__CYGWIN__))
|
||||
if (linkPtr->type == 11 /* legacy TCL_LINK_LONG */) {
|
||||
linkPtr->type = TCL_LINK_LONG;
|
||||
} else if (linkPtr->type == 12 /* legacy TCL_LINK_ULONG */) {
|
||||
linkPtr->type = TCL_LINK_ULONG;
|
||||
}
|
||||
#endif
|
||||
if (type & TCL_LINK_READ_ONLY) {
|
||||
linkPtr->flags = LINK_READ_ONLY;
|
||||
} else {
|
||||
@@ -263,7 +272,8 @@ LinkTraceProc(
|
||||
int flags) /* Miscellaneous additional information. */
|
||||
{
|
||||
Link *linkPtr = clientData;
|
||||
int changed, valueLength;
|
||||
int changed;
|
||||
size_t valueLength;
|
||||
const char *value;
|
||||
char **pp;
|
||||
Tcl_Obj *valueObj;
|
||||
@@ -335,12 +345,14 @@ LinkTraceProc(
|
||||
case TCL_LINK_UINT:
|
||||
changed = (LinkedVar(unsigned int) != linkPtr->lastValue.ui);
|
||||
break;
|
||||
#if !defined(TCL_WIDE_INT_IS_LONG) && !defined(_WIN32) && !defined(__CYGWIN__)
|
||||
case TCL_LINK_LONG:
|
||||
changed = (LinkedVar(long) != linkPtr->lastValue.l);
|
||||
break;
|
||||
case TCL_LINK_ULONG:
|
||||
changed = (LinkedVar(unsigned long) != linkPtr->lastValue.ul);
|
||||
break;
|
||||
#endif
|
||||
case TCL_LINK_FLOAT:
|
||||
changed = (LinkedVar(float) != linkPtr->lastValue.f);
|
||||
break;
|
||||
@@ -382,40 +394,31 @@ LinkTraceProc(
|
||||
|
||||
switch (linkPtr->type) {
|
||||
case TCL_LINK_INT:
|
||||
if (Tcl_GetIntFromObj(NULL, valueObj, &linkPtr->lastValue.i)
|
||||
!= TCL_OK) {
|
||||
if (GetInvalidIntFromObj(valueObj, &linkPtr->lastValue.i)
|
||||
!= TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
if (Tcl_GetIntFromObj(NULL, valueObj, &linkPtr->lastValue.i) != TCL_OK
|
||||
&& GetInvalidIntFromObj(valueObj, &linkPtr->lastValue.i) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have integer value";
|
||||
}
|
||||
return (char *) "variable must have integer value";
|
||||
}
|
||||
LinkedVar(int) = linkPtr->lastValue.i;
|
||||
break;
|
||||
|
||||
case TCL_LINK_WIDE_INT:
|
||||
if (Tcl_GetWideIntFromObj(NULL, valueObj, &linkPtr->lastValue.w)
|
||||
!= TCL_OK) {
|
||||
if (GetInvalidIntFromObj(valueObj, &valueInt)
|
||||
!= TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
if (Tcl_GetWideIntFromObj(NULL, valueObj, &linkPtr->lastValue.w) != TCL_OK
|
||||
&& GetInvalidWideFromObj(valueObj, &linkPtr->lastValue.w) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have integer value";
|
||||
}
|
||||
linkPtr->lastValue.w = (Tcl_WideInt) valueInt;
|
||||
return (char *) "variable must have integer value";
|
||||
}
|
||||
LinkedVar(Tcl_WideInt) = linkPtr->lastValue.w;
|
||||
break;
|
||||
|
||||
case TCL_LINK_DOUBLE:
|
||||
if (Tcl_GetDoubleFromObj(NULL, valueObj, &linkPtr->lastValue.d)
|
||||
!= TCL_OK) {
|
||||
if (Tcl_GetDoubleFromObj(NULL, valueObj, &linkPtr->lastValue.d) != TCL_OK) {
|
||||
#ifdef ACCEPT_NAN
|
||||
if (valueObj->typePtr != &tclDoubleType) {
|
||||
#endif
|
||||
if (GetInvalidDoubleFromObj(valueObj, &linkPtr->lastValue.d)
|
||||
!= TCL_OK) {
|
||||
if (GetInvalidDoubleFromObj(valueObj, &linkPtr->lastValue.d) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have real value";
|
||||
@@ -429,8 +432,7 @@ LinkTraceProc(
|
||||
break;
|
||||
|
||||
case TCL_LINK_BOOLEAN:
|
||||
if (Tcl_GetBooleanFromObj(NULL, valueObj, &linkPtr->lastValue.i)
|
||||
!= TCL_OK) {
|
||||
if (Tcl_GetBooleanFromObj(NULL, valueObj, &linkPtr->lastValue.i) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have boolean value";
|
||||
@@ -439,148 +441,115 @@ LinkTraceProc(
|
||||
break;
|
||||
|
||||
case TCL_LINK_CHAR:
|
||||
if (Tcl_GetIntFromObj(NULL, valueObj, &valueInt) != TCL_OK
|
||||
if ((Tcl_GetIntFromObj(NULL, valueObj, &valueInt) != TCL_OK
|
||||
&& GetInvalidIntFromObj(valueObj, &valueInt) != TCL_OK)
|
||||
|| valueInt < SCHAR_MIN || valueInt > SCHAR_MAX) {
|
||||
if (GetInvalidIntFromObj(valueObj, &valueInt)
|
||||
!= TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have char value";
|
||||
}
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have char value";
|
||||
}
|
||||
linkPtr->lastValue.c = (char)valueInt;
|
||||
LinkedVar(char) = linkPtr->lastValue.c;
|
||||
LinkedVar(char) = linkPtr->lastValue.c = (char)valueInt;
|
||||
break;
|
||||
|
||||
case TCL_LINK_UCHAR:
|
||||
if (Tcl_GetIntFromObj(NULL, valueObj, &valueInt) != TCL_OK
|
||||
if ((Tcl_GetIntFromObj(NULL, valueObj, &valueInt) != TCL_OK
|
||||
&& GetInvalidIntFromObj(valueObj, &valueInt) != TCL_OK)
|
||||
|| valueInt < 0 || valueInt > UCHAR_MAX) {
|
||||
if (GetInvalidIntFromObj(valueObj, &valueInt)
|
||||
!= TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned char value";
|
||||
}
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned char value";
|
||||
}
|
||||
linkPtr->lastValue.uc = (unsigned char) valueInt;
|
||||
LinkedVar(unsigned char) = linkPtr->lastValue.uc;
|
||||
LinkedVar(unsigned char) = linkPtr->lastValue.uc = (unsigned char) valueInt;
|
||||
break;
|
||||
|
||||
case TCL_LINK_SHORT:
|
||||
if (Tcl_GetIntFromObj(NULL, valueObj, &valueInt) != TCL_OK
|
||||
if ((Tcl_GetIntFromObj(NULL, valueObj, &valueInt) != TCL_OK
|
||||
&& GetInvalidIntFromObj(valueObj, &valueInt) != TCL_OK)
|
||||
|| valueInt < SHRT_MIN || valueInt > SHRT_MAX) {
|
||||
if (GetInvalidIntFromObj(valueObj, &valueInt)
|
||||
!= TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have short value";
|
||||
}
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have short value";
|
||||
}
|
||||
linkPtr->lastValue.s = (short)valueInt;
|
||||
LinkedVar(short) = linkPtr->lastValue.s;
|
||||
LinkedVar(short) = linkPtr->lastValue.s = (short)valueInt;
|
||||
break;
|
||||
|
||||
case TCL_LINK_USHORT:
|
||||
if (Tcl_GetIntFromObj(NULL, valueObj, &valueInt) != TCL_OK
|
||||
if ((Tcl_GetIntFromObj(NULL, valueObj, &valueInt) != TCL_OK
|
||||
&& GetInvalidIntFromObj(valueObj, &valueInt) != TCL_OK)
|
||||
|| valueInt < 0 || valueInt > USHRT_MAX) {
|
||||
if (GetInvalidIntFromObj(valueObj, &valueInt)
|
||||
!= TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned short value";
|
||||
}
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned short value";
|
||||
}
|
||||
linkPtr->lastValue.us = (unsigned short)valueInt;
|
||||
LinkedVar(unsigned short) = linkPtr->lastValue.us;
|
||||
LinkedVar(unsigned short) = linkPtr->lastValue.us = (unsigned short)valueInt;
|
||||
break;
|
||||
|
||||
case TCL_LINK_UINT:
|
||||
if (Tcl_GetWideIntFromObj(NULL, valueObj, &valueWide) != TCL_OK
|
||||
if ((Tcl_GetWideIntFromObj(NULL, valueObj, &valueWide) != TCL_OK
|
||||
&& GetInvalidWideFromObj(valueObj, &valueWide) != TCL_OK)
|
||||
|| valueWide < 0 || valueWide > UINT_MAX) {
|
||||
if (GetInvalidIntFromObj(valueObj, &valueInt)
|
||||
!= TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned int value";
|
||||
}
|
||||
linkPtr->lastValue.ui = (unsigned int)valueInt;
|
||||
} else {
|
||||
linkPtr->lastValue.ui = (unsigned int)valueWide;
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned int value";
|
||||
}
|
||||
LinkedVar(unsigned int) = linkPtr->lastValue.ui;
|
||||
LinkedVar(unsigned int) = linkPtr->lastValue.ui = (unsigned int)valueWide;
|
||||
break;
|
||||
|
||||
#if !defined(TCL_WIDE_INT_IS_LONG) && !defined(_WIN32) && !defined(__CYGWIN__)
|
||||
case TCL_LINK_LONG:
|
||||
if (Tcl_GetWideIntFromObj(NULL, valueObj, &valueWide) != TCL_OK
|
||||
if ((Tcl_GetWideIntFromObj(NULL, valueObj, &valueWide) != TCL_OK
|
||||
&& GetInvalidWideFromObj(valueObj, &valueWide) != TCL_OK)
|
||||
|| valueWide < LONG_MIN || valueWide > LONG_MAX) {
|
||||
if (GetInvalidIntFromObj(valueObj, &valueInt)
|
||||
!= TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have long value";
|
||||
}
|
||||
linkPtr->lastValue.l = (long)valueInt;
|
||||
} else {
|
||||
linkPtr->lastValue.l = (long)valueWide;
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have long value";
|
||||
}
|
||||
LinkedVar(long) = linkPtr->lastValue.l;
|
||||
LinkedVar(long) = linkPtr->lastValue.l = (long)valueWide;
|
||||
break;
|
||||
|
||||
case TCL_LINK_ULONG:
|
||||
if (Tcl_GetWideIntFromObj(NULL, valueObj, &valueWide) != TCL_OK
|
||||
if ((Tcl_GetWideIntFromObj(NULL, valueObj, &valueWide) != TCL_OK
|
||||
&& GetInvalidWideFromObj(valueObj, &valueWide) != TCL_OK)
|
||||
|| valueWide < 0 || (Tcl_WideUInt) valueWide > ULONG_MAX) {
|
||||
if (GetInvalidIntFromObj(valueObj, &valueInt)
|
||||
!= TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned long value";
|
||||
}
|
||||
linkPtr->lastValue.ul = (unsigned long)valueInt;
|
||||
} else {
|
||||
linkPtr->lastValue.ul = (unsigned long)valueWide;
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned long value";
|
||||
}
|
||||
LinkedVar(unsigned long) = linkPtr->lastValue.ul;
|
||||
LinkedVar(unsigned long) = linkPtr->lastValue.ul = (unsigned long)valueWide;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case TCL_LINK_WIDE_UINT:
|
||||
/*
|
||||
* FIXME: represent as a bignum.
|
||||
*/
|
||||
if (Tcl_GetWideIntFromObj(NULL, valueObj, &valueWide) != TCL_OK) {
|
||||
if (GetInvalidIntFromObj(valueObj, &valueInt)
|
||||
!= TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned wide int value";
|
||||
}
|
||||
linkPtr->lastValue.uw = (Tcl_WideUInt)valueInt;
|
||||
} else {
|
||||
linkPtr->lastValue.uw = (Tcl_WideUInt)valueWide;
|
||||
if (Tcl_GetWideIntFromObj(NULL, valueObj, &valueWide) != TCL_OK
|
||||
&& GetInvalidWideFromObj(valueObj, &valueWide) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned wide int value";
|
||||
}
|
||||
LinkedVar(Tcl_WideUInt) = linkPtr->lastValue.uw;
|
||||
LinkedVar(Tcl_WideUInt) = linkPtr->lastValue.uw = (Tcl_WideUInt)valueWide;
|
||||
break;
|
||||
|
||||
case TCL_LINK_FLOAT:
|
||||
if (Tcl_GetDoubleFromObj(NULL, valueObj, &valueDouble) != TCL_OK
|
||||
if ((Tcl_GetDoubleFromObj(NULL, valueObj, &valueDouble) != TCL_OK
|
||||
&& GetInvalidDoubleFromObj(valueObj, &valueDouble) != TCL_OK)
|
||||
|| valueDouble < -FLT_MAX || valueDouble > FLT_MAX) {
|
||||
if (GetInvalidDoubleFromObj(valueObj, &valueDouble)
|
||||
!= TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have float value";
|
||||
}
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have float value";
|
||||
}
|
||||
linkPtr->lastValue.f = (float)valueDouble;
|
||||
LinkedVar(float) = linkPtr->lastValue.f;
|
||||
LinkedVar(float) = linkPtr->lastValue.f = (float)valueDouble;
|
||||
break;
|
||||
|
||||
case TCL_LINK_STRING:
|
||||
value = TclGetStringFromObj(valueObj, &valueLength);
|
||||
valueLength++;
|
||||
value = TclGetString(valueObj);
|
||||
valueLength = valueObj->length + 1;
|
||||
pp = (char **) linkPtr->addr;
|
||||
|
||||
*pp = ckrealloc(*pp, valueLength);
|
||||
memcpy(*pp, value, (unsigned) valueLength);
|
||||
memcpy(*pp, value, valueLength);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -642,12 +611,14 @@ ObjValue(
|
||||
case TCL_LINK_UINT:
|
||||
linkPtr->lastValue.ui = LinkedVar(unsigned int);
|
||||
return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.ui);
|
||||
#if !defined(TCL_WIDE_INT_IS_LONG) && !defined(_WIN32) && !defined(__CYGWIN__)
|
||||
case TCL_LINK_LONG:
|
||||
linkPtr->lastValue.l = LinkedVar(long);
|
||||
return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.l);
|
||||
case TCL_LINK_ULONG:
|
||||
linkPtr->lastValue.ul = LinkedVar(unsigned long);
|
||||
return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.ul);
|
||||
#endif
|
||||
case TCL_LINK_FLOAT:
|
||||
linkPtr->lastValue.f = LinkedVar(float);
|
||||
return Tcl_NewDoubleObj(linkPtr->lastValue.f);
|
||||
@@ -688,17 +659,16 @@ static Tcl_ObjType invalidRealType = {
|
||||
|
||||
static int
|
||||
SetInvalidRealFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr) {
|
||||
int length;
|
||||
const char *str;
|
||||
const char *endPtr;
|
||||
|
||||
str = TclGetStringFromObj(objPtr, &length);
|
||||
if ((length == 1) && (str[0] == '.')){
|
||||
str = TclGetString(objPtr);
|
||||
if ((objPtr->length == 1) && (str[0] == '.')){
|
||||
objPtr->typePtr = &invalidRealType;
|
||||
objPtr->internalRep.doubleValue = 0.0;
|
||||
return TCL_OK;
|
||||
}
|
||||
if (TclParseNumber(NULL, objPtr, NULL, str, length, &endPtr,
|
||||
if (TclParseNumber(NULL, objPtr, NULL, str, objPtr->length, &endPtr,
|
||||
TCL_PARSE_DECIMAL_ONLY) == TCL_OK) {
|
||||
/* If number is followed by [eE][+-]?, then it is an invalid
|
||||
* double, but it could be the start of a valid double. */
|
||||
@@ -708,7 +678,7 @@ SetInvalidRealFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr) {
|
||||
if (*endPtr == 0) {
|
||||
double doubleValue = 0.0;
|
||||
Tcl_GetDoubleFromObj(NULL, objPtr, &doubleValue);
|
||||
if (objPtr->typePtr->freeIntRepProc) objPtr->typePtr->freeIntRepProc(objPtr);
|
||||
TclFreeIntRep(objPtr);
|
||||
objPtr->typePtr = &invalidRealType;
|
||||
objPtr->internalRep.doubleValue = doubleValue;
|
||||
return TCL_OK;
|
||||
@@ -722,48 +692,61 @@ SetInvalidRealFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr) {
|
||||
/*
|
||||
* This function checks for integer representations, which are valid
|
||||
* when linking with C variables, but which are invalid in other
|
||||
* contexts in Tcl. Handled are "+", "-", "0x", "0b" and "0o" (upper-
|
||||
* and lowercase). See bug [39f6304c2e].
|
||||
* contexts in Tcl. Handled are "+", "-", "", "0x", "0b" and "0o"
|
||||
* (upperand lowercase). See bug [39f6304c2e].
|
||||
*/
|
||||
int
|
||||
GetInvalidIntFromObj(Tcl_Obj *objPtr,
|
||||
int *intPtr)
|
||||
GetInvalidIntFromObj(Tcl_Obj *objPtr, int *intPtr)
|
||||
{
|
||||
int length;
|
||||
const char *str = TclGetStringFromObj(objPtr, &length);
|
||||
const char *str = TclGetString(objPtr);
|
||||
|
||||
if ((length == 1) && strchr("+-", str[0])) {
|
||||
*intPtr = (str[0] == '+');
|
||||
return TCL_OK;
|
||||
} else if ((length == 2) && (str[0] == '0') && strchr("xXbBoO", str[1])) {
|
||||
if ((objPtr->length == 0) ||
|
||||
((objPtr->length == 2) && (str[0] == '0') && strchr("xXbBoO", str[1]))) {
|
||||
*intPtr = 0;
|
||||
return TCL_OK;
|
||||
} else if ((objPtr->length == 1) && strchr("+-", str[0])) {
|
||||
*intPtr = (str[0] == '+');
|
||||
return TCL_OK;
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
int
|
||||
GetInvalidWideFromObj(Tcl_Obj *objPtr, Tcl_WideInt *widePtr)
|
||||
{
|
||||
int intValue;
|
||||
|
||||
if (GetInvalidIntFromObj(objPtr, &intValue) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
*widePtr = intValue;
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function checks for double representations, which are valid
|
||||
* when linking with C variables, but which are invalid in other
|
||||
* contexts in Tcl. Handled are ".", "+", "-", "0x", "0b" and "0o"
|
||||
* contexts in Tcl. Handled are "+", "-", "", ".", "0x", "0b" and "0o"
|
||||
* (upper- and lowercase) and sequences like "1e-". See bug [39f6304c2e].
|
||||
*/
|
||||
int
|
||||
GetInvalidDoubleFromObj(Tcl_Obj *objPtr,
|
||||
double *doublePtr)
|
||||
GetInvalidDoubleFromObj(Tcl_Obj *objPtr, double *doublePtr)
|
||||
{
|
||||
int intValue, result;
|
||||
int intValue;
|
||||
|
||||
if ((objPtr->typePtr == &invalidRealType) ||
|
||||
(SetInvalidRealFromAny(NULL, objPtr) == TCL_OK)) {
|
||||
if (objPtr->typePtr == &invalidRealType) {
|
||||
goto gotdouble;
|
||||
}
|
||||
if (GetInvalidIntFromObj(objPtr, &intValue) == TCL_OK) {
|
||||
*doublePtr = (double) intValue;
|
||||
return TCL_OK;
|
||||
}
|
||||
if (SetInvalidRealFromAny(NULL, objPtr) == TCL_OK) {
|
||||
gotdouble:
|
||||
*doublePtr = objPtr->internalRep.doubleValue;
|
||||
return TCL_OK;
|
||||
}
|
||||
result = GetInvalidIntFromObj(objPtr, &intValue);
|
||||
if (result == TCL_OK) {
|
||||
*doublePtr = (double) intValue;
|
||||
}
|
||||
return result;
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -374,7 +374,7 @@ Tcl_SetListObj(
|
||||
listRepPtr = NewListIntRep(objc, objv, 1);
|
||||
ListSetIntRep(objPtr, listRepPtr);
|
||||
} else {
|
||||
objPtr->bytes = tclEmptyStringRep;
|
||||
objPtr->bytes = &tclEmptyString;
|
||||
objPtr->length = 0;
|
||||
}
|
||||
}
|
||||
@@ -465,7 +465,7 @@ Tcl_ListObjGetElements(
|
||||
if (listPtr->typePtr != &tclListType) {
|
||||
int result;
|
||||
|
||||
if (listPtr->bytes == tclEmptyStringRep) {
|
||||
if (listPtr->bytes == &tclEmptyString) {
|
||||
*objcPtr = 0;
|
||||
*objvPtr = NULL;
|
||||
return TCL_OK;
|
||||
@@ -575,7 +575,7 @@ Tcl_ListObjAppendElement(
|
||||
if (listPtr->typePtr != &tclListType) {
|
||||
int result;
|
||||
|
||||
if (listPtr->bytes == tclEmptyStringRep) {
|
||||
if (listPtr->bytes == &tclEmptyString) {
|
||||
Tcl_SetListObj(listPtr, 1, &objPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -739,7 +739,7 @@ Tcl_ListObjIndex(
|
||||
if (listPtr->typePtr != &tclListType) {
|
||||
int result;
|
||||
|
||||
if (listPtr->bytes == tclEmptyStringRep) {
|
||||
if (listPtr->bytes == &tclEmptyString) {
|
||||
*objPtrPtr = NULL;
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -792,7 +792,7 @@ Tcl_ListObjLength(
|
||||
if (listPtr->typePtr != &tclListType) {
|
||||
int result;
|
||||
|
||||
if (listPtr->bytes == tclEmptyStringRep) {
|
||||
if (listPtr->bytes == &tclEmptyString) {
|
||||
*intPtr = 0;
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -863,7 +863,7 @@ Tcl_ListObjReplace(
|
||||
Tcl_Panic("%s called with shared object", "Tcl_ListObjReplace");
|
||||
}
|
||||
if (listPtr->typePtr != &tclListType) {
|
||||
if (listPtr->bytes == tclEmptyStringRep) {
|
||||
if (listPtr->bytes == &tclEmptyString) {
|
||||
if (!objc) {
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -1650,7 +1650,7 @@ TclListObjSetElement(
|
||||
if (listPtr->typePtr != &tclListType) {
|
||||
int result;
|
||||
|
||||
if (listPtr->bytes == tclEmptyStringRep) {
|
||||
if (listPtr->bytes == &tclEmptyString) {
|
||||
if (interp != NULL) {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewStringObj("list index out of range", -1));
|
||||
@@ -1979,7 +1979,7 @@ UpdateStringOfList(
|
||||
*/
|
||||
|
||||
if (numElems == 0) {
|
||||
listPtr->bytes = tclEmptyStringRep;
|
||||
listPtr->bytes = &tclEmptyString;
|
||||
listPtr->length = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
* limited to a single interpreter.
|
||||
*/
|
||||
|
||||
typedef struct ThreadSpecificData {
|
||||
typedef struct {
|
||||
size_t numNsCreated; /* Count of the number of namespaces created
|
||||
* within the thread. This value is used as a
|
||||
* unique id for each namespace. Cannot be
|
||||
|
||||
@@ -619,6 +619,7 @@ AddClassMethodNames(
|
||||
int isWanted = (!(flags & PUBLIC_METHOD)
|
||||
|| (mPtr->flags & PUBLIC_METHOD)) ? IN_LIST : 0;
|
||||
|
||||
isWanted |= (mPtr->typePtr == NULL ? NO_IMPLEMENTATION : 0);
|
||||
Tcl_SetHashValue(hPtr, INT2PTR(isWanted));
|
||||
} else if ((PTR2INT(Tcl_GetHashValue(hPtr)) & NO_IMPLEMENTATION)
|
||||
&& mPtr->typePtr != NULL) {
|
||||
|
||||
+37
-34
@@ -49,7 +49,6 @@ Tcl_Mutex tclObjMutex;
|
||||
*/
|
||||
|
||||
char tclEmptyString = '\0';
|
||||
char *tclEmptyStringRep = &tclEmptyString;
|
||||
|
||||
#if defined(TCL_MEM_DEBUG) && defined(TCL_THREADS)
|
||||
/*
|
||||
@@ -76,7 +75,7 @@ typedef struct ObjData {
|
||||
* The structure defined below is used in this file only.
|
||||
*/
|
||||
|
||||
typedef struct ThreadSpecificData {
|
||||
typedef struct {
|
||||
Tcl_HashTable *lineCLPtr; /* This table remembers for each Tcl_Obj
|
||||
* generated by a call to the function
|
||||
* TclSubstTokens() from a literal text
|
||||
@@ -345,17 +344,17 @@ typedef struct ResolvedCmdName {
|
||||
* reference (not the namespace that contains
|
||||
* the referenced command). NULL if the name
|
||||
* is fully qualified.*/
|
||||
long refNsId; /* refNsPtr's unique namespace id. Used to
|
||||
size_t refNsId; /* refNsPtr's unique namespace id. Used to
|
||||
* verify that refNsPtr is still valid (e.g.,
|
||||
* it's possible that the cmd's containing
|
||||
* namespace was deleted and a new one created
|
||||
* at the same address). */
|
||||
int refNsCmdEpoch; /* Value of the referencing namespace's
|
||||
size_t refNsCmdEpoch; /* Value of the referencing namespace's
|
||||
* cmdRefEpoch when the pointer was cached.
|
||||
* Before using the cached pointer, we check
|
||||
* if the namespace's epoch was incremented;
|
||||
* if so, this cached pointer is invalid. */
|
||||
int cmdEpoch; /* Value of the command's cmdEpoch when this
|
||||
size_t cmdEpoch; /* Value of the command's cmdEpoch when this
|
||||
* pointer was cached. Before using the cached
|
||||
* pointer, we check if the cmd's epoch was
|
||||
* incremented; if so, the cmd was renamed,
|
||||
@@ -1060,7 +1059,7 @@ TclDbInitNewObj(
|
||||
* debugging. */
|
||||
{
|
||||
objPtr->refCount = 0;
|
||||
objPtr->bytes = tclEmptyStringRep;
|
||||
objPtr->bytes = &tclEmptyString;
|
||||
objPtr->length = 0;
|
||||
objPtr->typePtr = NULL;
|
||||
|
||||
@@ -1733,7 +1732,7 @@ Tcl_InvalidateStringRep(
|
||||
* is coerced to 1.
|
||||
*
|
||||
* When TCL_MEM_DEBUG is defined, this function just returns the result
|
||||
* of calling the debugging version Tcl_DbNewBooleanObj.
|
||||
* of calling the debugging version Tcl_DbNewLongObj.
|
||||
*
|
||||
* Results:
|
||||
* The newly created object is returned. This object will have an invalid
|
||||
@@ -1752,7 +1751,7 @@ Tcl_Obj *
|
||||
Tcl_NewBooleanObj(
|
||||
register int boolValue) /* Boolean used to initialize new object. */
|
||||
{
|
||||
return Tcl_DbNewBooleanObj(boolValue, "unknown", 0);
|
||||
return Tcl_DbNewLongObj(boolValue!=0, "unknown", 0);
|
||||
}
|
||||
|
||||
#else /* if not TCL_MEM_DEBUG */
|
||||
@@ -1763,7 +1762,7 @@ Tcl_NewBooleanObj(
|
||||
{
|
||||
register Tcl_Obj *objPtr;
|
||||
|
||||
TclNewBooleanObj(objPtr, boolValue);
|
||||
TclNewLongObj(objPtr, boolValue!=0);
|
||||
return objPtr;
|
||||
}
|
||||
#endif /* TCL_MEM_DEBUG */
|
||||
@@ -1794,6 +1793,7 @@ Tcl_NewBooleanObj(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
#undef Tcl_DbNewBooleanObj
|
||||
#ifdef TCL_MEM_DEBUG
|
||||
|
||||
@@ -1857,8 +1857,9 @@ Tcl_SetBooleanObj(
|
||||
Tcl_Panic("%s called with shared object", "Tcl_SetBooleanObj");
|
||||
}
|
||||
|
||||
TclSetBooleanObj(objPtr, boolValue);
|
||||
TclSetLongObj(objPtr, boolValue!=0);
|
||||
}
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -2004,9 +2005,10 @@ static int
|
||||
ParseBoolean(
|
||||
register Tcl_Obj *objPtr) /* The object to parse/convert. */
|
||||
{
|
||||
int i, length, newBool;
|
||||
int newBool;
|
||||
char lowerCase[6];
|
||||
const char *str = TclGetStringFromObj(objPtr, &length);
|
||||
const char *str = TclGetString(objPtr);
|
||||
size_t i, length = objPtr->length;
|
||||
|
||||
if ((length == 0) || (length > 5)) {
|
||||
/*
|
||||
@@ -2058,25 +2060,25 @@ ParseBoolean(
|
||||
/*
|
||||
* Checking the 'y' is redundant, but makes the code clearer.
|
||||
*/
|
||||
if (strncmp(lowerCase, "yes", (size_t) length) == 0) {
|
||||
if (strncmp(lowerCase, "yes", length) == 0) {
|
||||
newBool = 1;
|
||||
goto goodBoolean;
|
||||
}
|
||||
return TCL_ERROR;
|
||||
case 'n':
|
||||
if (strncmp(lowerCase, "no", (size_t) length) == 0) {
|
||||
if (strncmp(lowerCase, "no", length) == 0) {
|
||||
newBool = 0;
|
||||
goto goodBoolean;
|
||||
}
|
||||
return TCL_ERROR;
|
||||
case 't':
|
||||
if (strncmp(lowerCase, "true", (size_t) length) == 0) {
|
||||
if (strncmp(lowerCase, "true", length) == 0) {
|
||||
newBool = 1;
|
||||
goto goodBoolean;
|
||||
}
|
||||
return TCL_ERROR;
|
||||
case 'f':
|
||||
if (strncmp(lowerCase, "false", (size_t) length) == 0) {
|
||||
if (strncmp(lowerCase, "false", length) == 0) {
|
||||
newBool = 0;
|
||||
goto goodBoolean;
|
||||
}
|
||||
@@ -2085,10 +2087,10 @@ ParseBoolean(
|
||||
if (length < 2) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (strncmp(lowerCase, "on", (size_t) length) == 0) {
|
||||
if (strncmp(lowerCase, "on", length) == 0) {
|
||||
newBool = 1;
|
||||
goto goodBoolean;
|
||||
} else if (strncmp(lowerCase, "off", (size_t) length) == 0) {
|
||||
} else if (strncmp(lowerCase, "off", length) == 0) {
|
||||
newBool = 0;
|
||||
goto goodBoolean;
|
||||
}
|
||||
@@ -2458,7 +2460,7 @@ Tcl_SetIntObj(
|
||||
Tcl_Panic("%s called with shared object", "Tcl_SetIntObj");
|
||||
}
|
||||
|
||||
TclSetIntObj(objPtr, intValue);
|
||||
TclSetLongObj(objPtr, intValue);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2784,7 +2786,7 @@ Tcl_GetLongFromObj(
|
||||
if (interp != NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"expected integer but got \"%s\"",
|
||||
Tcl_GetString(objPtr)));
|
||||
TclGetString(objPtr)));
|
||||
Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
@@ -3085,7 +3087,7 @@ Tcl_GetWideIntFromObj(
|
||||
if (interp != NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"expected integer but got \"%s\"",
|
||||
Tcl_GetString(objPtr)));
|
||||
TclGetString(objPtr)));
|
||||
Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
@@ -3394,7 +3396,7 @@ GetBignumFromObj(
|
||||
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
|
||||
objPtr->typePtr = NULL;
|
||||
if (objPtr->bytes == NULL) {
|
||||
TclInitStringRep(objPtr, tclEmptyStringRep, 0);
|
||||
TclInitStringRep(objPtr, &tclEmptyString, 0);
|
||||
}
|
||||
}
|
||||
return TCL_OK;
|
||||
@@ -3414,7 +3416,7 @@ GetBignumFromObj(
|
||||
if (interp != NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"expected integer but got \"%s\"",
|
||||
Tcl_GetString(objPtr)));
|
||||
TclGetString(objPtr)));
|
||||
Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
@@ -3964,7 +3966,7 @@ TclCompareObjKeys(
|
||||
Tcl_Obj *objPtr1 = keyPtr;
|
||||
Tcl_Obj *objPtr2 = (Tcl_Obj *) hPtr->key.oneWordValue;
|
||||
register const char *p1, *p2;
|
||||
register int l1, l2;
|
||||
register size_t l1, l2;
|
||||
|
||||
/*
|
||||
* If the object pointers are the same then they match.
|
||||
@@ -4453,7 +4455,6 @@ Tcl_RepresentationCmd(
|
||||
int objc,
|
||||
Tcl_Obj *const objv[])
|
||||
{
|
||||
char ptrBuffer[2*TCL_INTEGER_SPACE+6];
|
||||
Tcl_Obj *descObj;
|
||||
|
||||
if (objc != 2) {
|
||||
@@ -4467,18 +4468,20 @@ Tcl_RepresentationCmd(
|
||||
* "1872361827361287"
|
||||
*/
|
||||
|
||||
sprintf(ptrBuffer, "%p", (void *) objv[1]);
|
||||
descObj = Tcl_ObjPrintf("value is a %s with a refcount of %d,"
|
||||
" object pointer at %s",
|
||||
objv[1]->typePtr ? objv[1]->typePtr->name : "pure string",
|
||||
objv[1]->refCount, ptrBuffer);
|
||||
" object pointer at %p",
|
||||
objv[1]->typePtr ? objv[1]->typePtr->name : "pure string",
|
||||
objv[1]->refCount, objv[1]);
|
||||
|
||||
if (objv[1]->typePtr) {
|
||||
sprintf(ptrBuffer, "%p:%p",
|
||||
(void *) objv[1]->internalRep.twoPtrValue.ptr1,
|
||||
(void *) objv[1]->internalRep.twoPtrValue.ptr2);
|
||||
Tcl_AppendPrintfToObj(descObj, ", internal representation %s",
|
||||
ptrBuffer);
|
||||
if (objv[1]->typePtr == &tclDoubleType) {
|
||||
Tcl_AppendPrintfToObj(descObj, ", internal representation %g",
|
||||
objv[1]->internalRep.doubleValue);
|
||||
} else {
|
||||
Tcl_AppendPrintfToObj(descObj, ", internal representation %p:%p",
|
||||
(void *) objv[1]->internalRep.twoPtrValue.ptr1,
|
||||
(void *) objv[1]->internalRep.twoPtrValue.ptr2);
|
||||
}
|
||||
}
|
||||
|
||||
if (objv[1]->bytes) {
|
||||
|
||||
+4
-1
@@ -1169,6 +1169,8 @@ ParseTokens(
|
||||
numBytes--;
|
||||
nestedPtr = 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;
|
||||
@@ -1177,8 +1179,9 @@ ParseTokens(
|
||||
TclStackFree(parsePtr->interp, nestedPtr);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
curEnd = src + numBytes;
|
||||
src = nestedPtr->commandStart + nestedPtr->commandSize;
|
||||
numBytes = parsePtr->end - src;
|
||||
numBytes = curEnd - src;
|
||||
Tcl_FreeParse(nestedPtr);
|
||||
|
||||
/*
|
||||
|
||||
+19
-2
@@ -921,7 +921,17 @@ TclJoinPath(
|
||||
if (res != NULL) {
|
||||
TclDecrRefCount(res);
|
||||
}
|
||||
return TclNewFSPathObj(elt, str, len);
|
||||
|
||||
if (PATHFLAGS(elt)) {
|
||||
return TclNewFSPathObj(elt, str, len);
|
||||
}
|
||||
if (TCL_PATH_ABSOLUTE != Tcl_FSGetPathType(elt)) {
|
||||
return TclNewFSPathObj(elt, str, len);
|
||||
}
|
||||
(void) Tcl_FSGetNormalizedPath(NULL, elt);
|
||||
if (elt == PATHOBJ(elt)->normPathPtr) {
|
||||
return TclNewFSPathObj(elt, str, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -948,6 +958,7 @@ TclJoinPath(
|
||||
}
|
||||
}
|
||||
strElt = TclGetStringFromObj(elt, &strEltLen);
|
||||
driveNameLength = 0;
|
||||
type = TclGetPathType(elt, &fsPtr, &driveNameLength, &driveName);
|
||||
if (type != TCL_PATH_RELATIVE) {
|
||||
/*
|
||||
@@ -1003,6 +1014,12 @@ TclJoinPath(
|
||||
}
|
||||
}
|
||||
ptr = strElt;
|
||||
/* [Bug f34cf83dd0] */
|
||||
if (driveNameLength > 0) {
|
||||
if (ptr[0] == '/' && ptr[-1] == '/') {
|
||||
goto noQuickReturn;
|
||||
}
|
||||
}
|
||||
while (*ptr != '\0') {
|
||||
if (*ptr == '/' && (ptr[1] == '/' || ptr[1] == '\0')) {
|
||||
/*
|
||||
@@ -2608,7 +2625,7 @@ UpdateStringOfFsPath(
|
||||
|
||||
pathPtr->bytes = TclGetStringFromObj(copy, &cwdLen);
|
||||
pathPtr->length = cwdLen;
|
||||
copy->bytes = tclEmptyStringRep;
|
||||
copy->bytes = &tclEmptyString;
|
||||
copy->length = 0;
|
||||
TclDecrRefCount(copy);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
|
||||
#include "tclInt.h"
|
||||
|
||||
MODULE_SCOPE char *tclEmptyStringRep;
|
||||
|
||||
char *tclEmptyStringRep = &tclEmptyString;
|
||||
|
||||
/*
|
||||
* Each invocation of the "package ifneeded" command creates a structure of
|
||||
* the following type, which is used to load the package into the interpreter
|
||||
@@ -28,6 +32,7 @@ typedef struct PkgAvail {
|
||||
char *script; /* Script to invoke to provide this version of
|
||||
* the package. Malloc'ed and protected by
|
||||
* Tcl_Preserve and Tcl_Release. */
|
||||
char *pkgIndex; /* Full file name of pkgIndex file */
|
||||
struct PkgAvail *nextPtr; /* Next in list of available versions of the
|
||||
* same package. */
|
||||
} PkgAvail;
|
||||
@@ -569,6 +574,9 @@ PkgRequireCore(
|
||||
pkgName->nextPtr = pkgFiles->names;
|
||||
strcpy(pkgName->name, name);
|
||||
pkgFiles->names = pkgName;
|
||||
if (bestPtr->pkgIndex) {
|
||||
TclPkgFileSeen(interp, bestPtr->pkgIndex);
|
||||
}
|
||||
code = Tcl_EvalEx(interp, script, -1, TCL_EVAL_GLOBAL);
|
||||
/* Pop the "ifneeded" package name from "tclPkgFiles" assocdata*/
|
||||
pkgFiles->names = pkgName->nextPtr;
|
||||
@@ -917,6 +925,9 @@ Tcl_PackageObjCmd(
|
||||
pkgPtr->availPtr = availPtr->nextPtr;
|
||||
Tcl_EventuallyFree(availPtr->version, TCL_DYNAMIC);
|
||||
Tcl_EventuallyFree(availPtr->script, TCL_DYNAMIC);
|
||||
if (availPtr->pkgIndex) {
|
||||
Tcl_EventuallyFree(availPtr->pkgIndex, TCL_DYNAMIC);
|
||||
}
|
||||
ckfree(availPtr);
|
||||
}
|
||||
ckfree(pkgPtr);
|
||||
@@ -967,6 +978,9 @@ Tcl_PackageObjCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
Tcl_EventuallyFree(availPtr->script, TCL_DYNAMIC);
|
||||
if (availPtr->pkgIndex) {
|
||||
Tcl_EventuallyFree(availPtr->pkgIndex, TCL_DYNAMIC);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -977,6 +991,7 @@ Tcl_PackageObjCmd(
|
||||
}
|
||||
if (availPtr == NULL) {
|
||||
availPtr = ckalloc(sizeof(PkgAvail));
|
||||
availPtr->pkgIndex = 0;
|
||||
DupBlock(availPtr->version, argv3, (unsigned) length + 1);
|
||||
|
||||
if (prevPtr == NULL) {
|
||||
@@ -987,6 +1002,10 @@ Tcl_PackageObjCmd(
|
||||
prevPtr->nextPtr = availPtr;
|
||||
}
|
||||
}
|
||||
if (iPtr->scriptFile) {
|
||||
argv4 = TclGetStringFromObj(iPtr->scriptFile, &length);
|
||||
DupBlock(availPtr->pkgIndex, argv4, (unsigned) length + 1);
|
||||
}
|
||||
argv4 = TclGetStringFromObj(objv[4], &length);
|
||||
DupBlock(availPtr->script, argv4, (unsigned) length + 1);
|
||||
break;
|
||||
@@ -1342,6 +1361,9 @@ TclFreePackageInfo(
|
||||
pkgPtr->availPtr = availPtr->nextPtr;
|
||||
Tcl_EventuallyFree(availPtr->version, TCL_DYNAMIC);
|
||||
Tcl_EventuallyFree(availPtr->script, TCL_DYNAMIC);
|
||||
if (availPtr->pkgIndex) {
|
||||
Tcl_EventuallyFree(availPtr->pkgIndex, TCL_DYNAMIC);
|
||||
}
|
||||
ckfree(availPtr);
|
||||
}
|
||||
ckfree(pkgPtr);
|
||||
|
||||
@@ -155,7 +155,7 @@ Tcl_Preserve(
|
||||
refPtr->clientData = clientData;
|
||||
refPtr->refCount = 1;
|
||||
refPtr->mustFree = 0;
|
||||
refPtr->freeProc = TCL_STATIC;
|
||||
refPtr->freeProc = 0;
|
||||
inUse += 1;
|
||||
Tcl_MutexUnlock(&preserveMutex);
|
||||
}
|
||||
|
||||
+40
-5
@@ -500,7 +500,8 @@ TclCreateProc(
|
||||
}
|
||||
|
||||
for (i = 0; i < numArgs; i++) {
|
||||
int fieldCount, nameLength, valueLength;
|
||||
int fieldCount, nameLength;
|
||||
size_t valueLength;
|
||||
const char **fieldValues;
|
||||
|
||||
/*
|
||||
@@ -602,12 +603,11 @@ TclCreateProc(
|
||||
*/
|
||||
|
||||
if (localPtr->defValuePtr != NULL) {
|
||||
int tmpLength;
|
||||
const char *tmpPtr = TclGetStringFromObj(localPtr->defValuePtr,
|
||||
&tmpLength);
|
||||
const char *tmpPtr = TclGetString(localPtr->defValuePtr);
|
||||
size_t tmpLength = localPtr->defValuePtr->length;
|
||||
|
||||
if ((valueLength != tmpLength) ||
|
||||
strncmp(fieldValues[1], tmpPtr, (size_t) tmpLength)) {
|
||||
strncmp(fieldValues[1], tmpPtr, tmpLength)) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"procedure \"%s\": formal parameter \"%s\" has "
|
||||
"default value inconsistent with precompiled body",
|
||||
@@ -2749,6 +2749,41 @@ MakeLambdaError(
|
||||
(overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclGetCmdFrameForProcedure --
|
||||
*
|
||||
* How to get the CmdFrame information for a procedure.
|
||||
*
|
||||
* Results:
|
||||
* A pointer to the CmdFrame (only guaranteed to be valid until the next
|
||||
* Tcl command is processed or the interpreter's state is otherwise
|
||||
* modified) or a NULL if the information is not available.
|
||||
*
|
||||
* Side effects:
|
||||
* none.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
CmdFrame *
|
||||
TclGetCmdFrameForProcedure(
|
||||
Proc *procPtr) /* The procedure whose cmd-frame is to be
|
||||
* looked up. */
|
||||
{
|
||||
Tcl_HashEntry *hePtr;
|
||||
|
||||
if (procPtr == NULL || procPtr->iPtr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
hePtr = Tcl_FindHashEntry(procPtr->iPtr->linePBodyPtr, procPtr);
|
||||
if (hePtr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return (CmdFrame *) Tcl_GetHashValue(hePtr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: c
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user