diff --git a/.gitignore b/.gitignore index c629fd5d..052acb3c 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ # trees (generated .c/.h, the mrbc tool, CMake cache) under their own build/ dirs. /vendor/mruby/build/ /vendor/libssh2/build/ +/vendor/tcl/build/ # ...and mruby's Rake drops a transient per-config lock next to the config (src/mruby/). /src/mruby/*.lock diff --git a/API.md b/API.md index ea81cc8d..bfdc1300 100644 --- a/API.md +++ b/API.md @@ -84,7 +84,7 @@ Share a function by name across contexts and engines. |---|---| | `calogExport(name: string, fn: fn)` | Publish function `fn` under a global `name`. | | `calogUnexport(name: string)` | Remove an exported name. | -| `calogCall(name: string, ...args: any) -> any` | Call an exported function by name -- works in **every** engine. (An export is also reachable by its bare name -- `exportedFn(args)` -- on Lua/JS/Squirrel/s7, on Ruby at top level (via `method_missing`), and on my-basic case-insensitively (it uppercases identifiers); Wren and Berry always need `calogCall`.) | +| `calogCall(name: string, ...args: any) -> any` | Call an exported function by name -- works in **every** engine. (An export is also reachable by its bare name -- `exportedFn(args)` -- on Lua/JS/Squirrel/s7, on Ruby at top level (via `method_missing`), on Tcl (via its `unknown` handler), and on my-basic case-insensitively (it uppercases identifiers); Wren and Berry always need `calogCall`.) | ## fs @@ -208,7 +208,7 @@ out, or the close blocks until the task next returns to the runtime. | Function | Description | |---|---| -| `taskSpawn(engine: string, code: string) -> handle` | Run a code string on a named engine (`"lua"`, `"js"`, `"squirrel"`, `"mybasic"`, `"berry"`, `"s7"`, `"wren"`, `"mruby"`). | +| `taskSpawn(engine: string, code: string) -> handle` | Run a code string on a named engine (`"lua"`, `"js"`, `"squirrel"`, `"mybasic"`, `"berry"`, `"s7"`, `"wren"`, `"mruby"`, `"tcl"`). | | `taskLoad(baseName: string) -> handle` | Launch a script *file* (engine chosen by extension). | | `taskEval(handle: handle, code: string)` | Feed more code into a running task (runs on its thread). | | `taskClose(handle: handle)` | Ask a task to stop (cooperative: sets its shutdown flag, then waits for its thread to exit). | diff --git a/LICENSE.md b/LICENSE.md index 004d1fc2..7330ac72 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -70,6 +70,12 @@ libraries below. `vendor/mruby/` (unmodified upstream; license in `vendor/mruby/LICENSE`, contributors in `vendor/mruby/AUTHORS`). `libmruby.a` is generated by mruby's own Rake build (needs a host Ruby + bison at build time); calog links the resulting static archive. +- **Tcl 9.0.4** (Tool Command Language) -- Tcl/Tk License (BSD-style, permissive; allows + binary-only redistribution, no copyleft). Copyright (c) the Tcl Core Team and contributors. + `vendor/tcl/` (unmodified upstream, trimmed to the core: `generic`/`unix`/`compat`/ + `libtommath`/`library`; license in `vendor/tcl/license.terms`). `libtcl9.0.a` is produced by + Tcl's own autoconf build (`configure --disable-shared`, out of tree into `vendor/tcl/build/`); + calog links the resulting static archive (`-ldl -lz -lpthread -lm`). ### Database, network, and cryptography libraries diff --git a/Makefile b/Makefile index 1ae64df0..75c170af 100644 --- a/Makefile +++ b/Makefile @@ -27,8 +27,8 @@ LDFLAGS = $(SAN) # Our headers: src/ plus the per-language subdirs. VPATH lets the object rules find # a source by name without spelling out its directory. -INC = -Isrc -Isrc/lua -Isrc/mybasic -Isrc/squirrel -Isrc/js -Isrc/berry -Isrc/s7 -Isrc/wren -Isrc/mruby -Ilibs -VPATH = src:src/lua:src/mybasic:src/squirrel:src/js:src/berry:src/s7:src/wren:src/mruby:libs:tests +INC = -Isrc -Isrc/lua -Isrc/mybasic -Isrc/squirrel -Isrc/js -Isrc/berry -Isrc/s7 -Isrc/wren -Isrc/mruby -Isrc/tcl -Ilibs +VPATH = src:src/lua:src/mybasic:src/squirrel:src/js:src/berry:src/s7:src/wren:src/mruby:src/tcl:libs:tests # --- vendored our-basic: calog's fork of MY-BASIC (see vendor/ourbasic/NOTICE) --- MBDIR = vendor/ourbasic @@ -135,6 +135,20 @@ MRUBYLIBS = -lm $(MRUBYLIB): $(MRUBYCONF) cd $(MRUBYDIR) && MRUBY_CONFIG=$(MRUBYCONF) ruby ./minirake -j4 +# --- vendored Tcl 9.0.4 (Tool Command Language). Like libssh2/mruby, libtcl is produced by the +# engine's own build (autoconf): configure --disable-shared + make the static-lib target, OUT of +# tree into vendor/tcl/build/ (so the vendored source stays pristine). No host deps beyond a C +# toolchain; Tcl bundles zlib fallback + libtommath. Apartment threading (one Tcl_Interp per +# thread, no GIL) is mandatory in 9.0. Links -ldl -lz -lpthread -lm. tcl.h needs no generated +# header (config is compiled in via -D), so the adapter builds against generic/ + unix/. --- +TCLDIR = vendor/tcl +TCLINC = -I$(TCLDIR)/generic -I$(TCLDIR)/unix +TCLLIB = $(TCLDIR)/build/libtcl9.0.a +TCLLIBS = -ldl -lz -lpthread -lm + +$(TCLLIB): + mkdir -p $(TCLDIR)/build && cd $(TCLDIR)/build && ../unix/configure --disable-shared >/dev/null && $(MAKE) libtcl9.0.a + # --- vendored SQLite (C amalgamation, single file). THREADSAFE=1 (serialized) because # the DB natives run inline on many context threads. Links -lm -lpthread. --- SQLITEDIR = vendor/sqlite @@ -152,19 +166,19 @@ ENETOBJ = $(foreach n,$(ENETNAMES),obj/enet_$(n).o) BINS = bin/testBroker bin/testLua bin/testMyBasic bin/testPolyglot bin/testActor \ bin/testEngineLua bin/testEngineMyBasic bin/testSquirrel bin/testEngineSquirrel bin/testJs bin/testEngineJs \ - bin/testEngineBerry bin/testEngineS7 bin/testEngineWren bin/testEngineMruby bin/testLoad bin/testDb bin/testNet bin/testTask bin/testExport bin/testJson bin/testTime bin/testFs bin/testCrypto bin/testKv bin/testTimer bin/testPubsub bin/testHttp bin/testHttps bin/embed bin/calog + bin/testEngineBerry bin/testEngineS7 bin/testEngineWren bin/testEngineMruby bin/testEngineTcl bin/testLoad bin/testDb bin/testNet bin/testTask bin/testExport bin/testJson bin/testTime bin/testFs bin/testCrypto bin/testKv bin/testTimer bin/testPubsub bin/testHttp bin/testHttps bin/embed bin/calog all: $(BINS) # ---- object rules, grouped by flag set (sources resolved via VPATH) ---- # strict C, no threads -STRICTOBJ = obj/broker.o obj/value.o obj/luaEngine.o obj/squirrelEngine.o obj/jsEngine.o obj/berryEngine.o obj/s7Engine.o obj/wrenEngine.o obj/mrubyEngine.o obj/testBroker.o +STRICTOBJ = obj/broker.o obj/value.o obj/luaEngine.o obj/squirrelEngine.o obj/jsEngine.o obj/berryEngine.o obj/s7Engine.o obj/wrenEngine.o obj/mrubyEngine.o obj/tclEngine.o obj/testBroker.o $(STRICTOBJ): obj/%.o: %.c | obj $(CC) $(COREFLAGS) $(INC) -c -o $@ $< # strict C, threaded -THREADOBJ = obj/context.o obj/mybasicEngine.o obj/testActor.o obj/testEngineLua.o obj/testEngineSquirrel.o obj/testEngineJs.o obj/testEngineMyBasic.o obj/testEngineBerry.o obj/testEngineS7.o obj/testEngineWren.o obj/testEngineMruby.o obj/calogHandle.o obj/testDb.o obj/testNet.o obj/testTask.o obj/calogExport.o obj/testExport.o obj/calogJson.o obj/testJson.o obj/calogFs.o obj/testFs.o obj/calogTime.o obj/testTime.o obj/calogKv.o obj/testKv.o obj/testCrypto.o obj/calogTimer.o obj/testTimer.o obj/calogPubsub.o obj/testPubsub.o obj/testHttp.o obj/testSsh.o +THREADOBJ = obj/context.o obj/mybasicEngine.o obj/testActor.o obj/testEngineLua.o obj/testEngineSquirrel.o obj/testEngineJs.o obj/testEngineMyBasic.o obj/testEngineBerry.o obj/testEngineS7.o obj/testEngineWren.o obj/testEngineMruby.o obj/testEngineTcl.o obj/calogHandle.o obj/testDb.o obj/testNet.o obj/testTask.o obj/calogExport.o obj/testExport.o obj/calogJson.o obj/testJson.o obj/calogFs.o obj/testFs.o obj/calogTime.o obj/testTime.o obj/calogKv.o obj/testKv.o obj/testCrypto.o obj/calogTimer.o obj/testTimer.o obj/calogPubsub.o obj/testPubsub.o obj/testHttp.o obj/testSsh.o $(THREADOBJ): obj/%.o: %.c | obj $(CC) $(COREFLAGS) $(INC) -pthread -c -o $@ $< @@ -228,6 +242,11 @@ MRUBYADP = obj/mrubyAdapter.o $(MRUBYADP): obj/%.o: %.c | obj $(MRUBYLIB) $(CC) $(ADPFLAGS) $(INC) $(MRUBYINC) -c -o $@ $< +# relaxed C + Tcl headers (tcl.h needs no generated header, so no $(TCLLIB) order dependency). +TCLADP = obj/tclAdapter.o +$(TCLADP): obj/%.o: %.c | obj + $(CC) $(ADPFLAGS) $(INC) $(TCLINC) -c -o $@ $< + # DB library adapter: relaxed C + SQLite headers, sqlite backend compiled in DBADP = obj/calogDb.o $(DBADP): obj/%.o: %.c | obj @@ -241,7 +260,7 @@ $(NETADP): obj/%.o: %.c | obj # task library: strict C with every engine name compiled in (it references each engine # vtable under its CALOG_WITH_* guard), so a task-using binary links all engine archives. -ENGINEDEFS = -DCALOG_WITH_LUA -DCALOG_WITH_JS -DCALOG_WITH_SQUIRREL -DCALOG_WITH_MYBASIC -DCALOG_WITH_BERRY -DCALOG_WITH_S7 -DCALOG_WITH_WREN -DCALOG_WITH_MRUBY +ENGINEDEFS = -DCALOG_WITH_LUA -DCALOG_WITH_JS -DCALOG_WITH_SQUIRREL -DCALOG_WITH_MYBASIC -DCALOG_WITH_BERRY -DCALOG_WITH_S7 -DCALOG_WITH_WREN -DCALOG_WITH_MRUBY -DCALOG_WITH_TCL TASKADP = obj/calogTask.o $(TASKADP): obj/%.o: %.c | obj $(CC) $(COREFLAGS) $(INC) $(ENGINEDEFS) -pthread -c -o $@ $< @@ -295,7 +314,7 @@ CALOGLIB = obj/value.o obj/broker.o obj/context.o \ obj/luaAdapter.o obj/luaEngine.o obj/jsAdapter.o obj/jsEngine.o \ obj/squirrelAdapter.o obj/squirrelEngine.o obj/mybasicAdapter.o obj/mybasicEngine.o \ obj/berryAdapter.o obj/berryEngine.o obj/s7Adapter.o obj/s7Engine.o obj/wrenAdapter.o obj/wrenEngine.o \ - obj/mrubyAdapter.o obj/mrubyEngine.o + obj/mrubyAdapter.o obj/mrubyEngine.o obj/tclAdapter.o obj/tclEngine.o lib/libcalog.a: $(CALOGLIB) | lib ar rcs $@ $^ @@ -402,6 +421,9 @@ bin/testEngineWren: obj/testEngineWren.o lib/libcalog.a lib/libwren.a | bin bin/testEngineMruby: obj/testEngineMruby.o lib/libcalog.a $(MRUBYLIB) | bin $(CC) $(LDFLAGS) -pthread -o $@ $^ $(MRUBYLIBS) +bin/testEngineTcl: obj/testEngineTcl.o lib/libcalog.a $(TCLLIB) | bin + $(CC) $(LDFLAGS) -pthread -o $@ $^ $(TCLLIBS) + # example host: embeds calog + JS via calog.h only, linking the two archives. obj/embed.o: examples/embed.c src/calog.h | obj $(CC) $(COREFLAGS) -Isrc -pthread -c -o $@ $< @@ -417,7 +439,7 @@ bin/embed: obj/embed.o lib/libcalog.a lib/libquickjs.a | bin # it); SSLARCH follows the archives that reference it. bin/calog: obj/calogMain.o \ obj/calogCrypto.o obj/calogDbFull.o obj/calogExport.o obj/calogFs.o obj/calogHttp.o obj/calogJson.o obj/calogKv.o obj/calogNet.o obj/calogPubsub.o obj/calogSsh.o obj/calogTask.o obj/calogTime.o obj/calogTimer.o obj/calogHandle.o \ - lib/libcalog.a lib/liblua.a lib/libquickjs.a lib/libsquirrel.a lib/libmybasic.a lib/libberry.a lib/libs7.a lib/libwren.a $(MRUBYLIB) \ + lib/libcalog.a lib/liblua.a lib/libquickjs.a lib/libsquirrel.a lib/libmybasic.a lib/libberry.a lib/libs7.a lib/libwren.a $(MRUBYLIB) $(TCLLIB) \ lib/libsqlite3.a lib/libenet.a $(LIBSSH2LIB) $(DBARCH) | bin $(CC) $(LDFLAGS) -pthread -o $@ $(filter-out $(DBARCH),$^) -Wl,--start-group $(PGARCHIVES) -Wl,--end-group $(MYSQLARCH) $(SSLARCH) -lstdc++ -ldl -lm -lpthread @@ -456,12 +478,12 @@ static: bin/calogStatic obj/testLoad.o: tests/testLoad.c src/calog.h | obj $(CC) $(COREFLAGS) -Isrc -pthread $(ENGINEDEFS) -c -o $@ $< -bin/testLoad: obj/testLoad.o lib/libcalog.a lib/liblua.a lib/libquickjs.a lib/libsquirrel.a lib/libmybasic.a lib/libberry.a lib/libs7.a lib/libwren.a $(MRUBYLIB) | bin - $(CC) $(LDFLAGS) -pthread -o $@ $^ $(LUALIBS) -lstdc++ -lm $(MRUBYLIBS) +bin/testLoad: obj/testLoad.o lib/libcalog.a lib/liblua.a lib/libquickjs.a lib/libsquirrel.a lib/libmybasic.a lib/libberry.a lib/libs7.a lib/libwren.a $(MRUBYLIB) $(TCLLIB) | bin + $(CC) $(LDFLAGS) -pthread -o $@ $^ $(LUALIBS) -lstdc++ -lm $(MRUBYLIBS) $(TCLLIBS) # task library test: the task lib names every engine, so (like testLoad) it links them all. -bin/testTask: obj/testTask.o $(TASKADP) obj/calogHandle.o lib/libcalog.a lib/liblua.a lib/libquickjs.a lib/libsquirrel.a lib/libmybasic.a lib/libberry.a lib/libs7.a lib/libwren.a $(MRUBYLIB) | bin - $(CC) $(LDFLAGS) -pthread -o $@ $^ $(LUALIBS) -lstdc++ -lm $(MRUBYLIBS) +bin/testTask: obj/testTask.o $(TASKADP) obj/calogHandle.o lib/libcalog.a lib/liblua.a lib/libquickjs.a lib/libsquirrel.a lib/libmybasic.a lib/libberry.a lib/libs7.a lib/libwren.a $(MRUBYLIB) $(TCLLIB) | bin + $(CC) $(LDFLAGS) -pthread -o $@ $^ $(LUALIBS) -lstdc++ -lm $(MRUBYLIBS) $(TCLLIBS) # export library test: publish from Lua, call by bare name from Lua + via callExport from JS. bin/testExport: obj/testExport.o obj/calogExport.o lib/libcalog.a lib/liblua.a lib/libquickjs.a lib/libsquirrel.a lib/libs7.a lib/libmybasic.a | bin @@ -510,7 +532,7 @@ obj bin lib: test: all ./bin/testBroker && ./bin/testLua && ./bin/testMyBasic && ./bin/testPolyglot && \ ./bin/testActor && ./bin/testEngineLua && ./bin/testEngineMyBasic && ./bin/testSquirrel && ./bin/testEngineSquirrel && \ - ./bin/testJs && ./bin/testEngineJs && ./bin/testEngineBerry && ./bin/testEngineS7 && ./bin/testEngineWren && ./bin/testEngineMruby && ./bin/testLoad && ./bin/testDb && ./bin/testNet && ./bin/testTask && ./bin/testExport && ./bin/testJson && ./bin/testTime && ./bin/testFs && ./bin/testCrypto && ./bin/testKv && ./bin/testTimer && ./bin/testPubsub && ./bin/testHttp && ./bin/testHttps + ./bin/testJs && ./bin/testEngineJs && ./bin/testEngineBerry && ./bin/testEngineS7 && ./bin/testEngineWren && ./bin/testEngineMruby && ./bin/testEngineTcl && ./bin/testLoad && ./bin/testDb && ./bin/testNet && ./bin/testTask && ./bin/testExport && ./bin/testJson && ./bin/testTime && ./bin/testFs && ./bin/testCrypto && ./bin/testKv && ./bin/testTimer && ./bin/testPubsub && ./bin/testHttp && ./bin/testHttps # ThreadSanitizer build of the actor core and the Lua engine path (cannot combine # with ASan). Recompiled from source under TSan; the vendored Lua objects are @@ -603,6 +625,15 @@ tsanmruby: $(MRUBYLIB) | bin obj $(MRUBYLIB) $(MRUBYLIBS) setarch -R ./bin/testEngineMrubyTsan +# ThreadSanitizer build of the Tcl engine path. Like tsanmruby, libtcl is a separately-built +# archive linked UN-sanitized; TSan instruments the calog adapter/engine/actor code, where the +# cross-context risk lives. Tcl's apartment model gives each thread its own interpreter. +tsantcl: $(TCLLIB) | bin obj + $(CC) $(TSANFLAGS) $(INC) $(TCLINC) -o bin/testEngineTclTsan \ + tests/testEngineTcl.c src/tcl/tclEngine.c src/tcl/tclAdapter.c $(TSANCORE) \ + $(TCLLIB) $(TCLLIBS) + setarch -R ./bin/testEngineTclTsan + # ThreadSanitizer build of the concurrent libraries (timer's background thread, pubsub's # callback fan-out, kv's shared store), each over a Lua context so callbacks marshal across # threads. The unsanitized liblua.a links in fine (TSan instruments only the calog code). @@ -620,4 +651,4 @@ clean: -include $(wildcard obj/*.d) -include $(wildcard obj/rel/*.d) -.PHONY: all test tsan tsansq tsanjs tsanmb tsanberry tsans7 tsanwren tsanmruby tsanlibs clean +.PHONY: all test tsan tsansq tsanjs tsanmb tsanberry tsans7 tsanwren tsanmruby tsantcl tsanlibs clean diff --git a/README.md b/README.md index 864a6bc1..6838918a 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,8 @@ **C: Any Language, One Gateway.** calog embeds scripting into a C or C++ program. You register your native C functions -**once**, and they become callable from **any** embedded engine — Lua, JavaScript, Scheme, -Squirrel, Wren, Berry, Ruby, or MY-BASIC — with values passed through a single canonical type. Add a new +**once**, and they become callable from **any** embedded engine -- Lua, JavaScript, Scheme, +Squirrel, Wren, Berry, Ruby, Tcl, or MY-BASIC -- with values passed through a single canonical type. Add a new scripting language to your app by linking one more archive; your native functions don't change. @@ -19,7 +19,7 @@ calogContextEval(ctx, "hostLog('hello from JavaScript, ' + 6 * 7)"); ``` Swap `&calogJsEngine` for `&calogLuaEngine`, `&calogSquirrelEngine`, -`&calogS7Engine`, `&calogWrenEngine`, `&calogBerryEngine`, `&calogMrubyEngine`, or `&calogMyBasicEngine` — nothing else changes. +`&calogS7Engine`, `&calogWrenEngine`, `&calogBerryEngine`, `&calogMrubyEngine`, `&calogTclEngine`, or `&calogMyBasicEngine` -- nothing else changes. --- @@ -27,11 +27,11 @@ Swap `&calogJsEngine` for `&calogLuaEngine`, `&calogSquirrelEngine`, - **One API, many languages.** Register a native once; call it from every engine. `calog.h` is the entire public surface. -- **One value type.** Everything crosses the boundary as a `CalogValueT` — nil, bool, +- **One value type.** Everything crosses the boundary as a `CalogValueT` -- nil, bool, int, real, binary-safe string, a hybrid list/map aggregate, or a script function value. No per-engine glue in your code. - **Natives run on your thread, serialized.** A script calling a native is marshalled to - the host thread and run there during `calogPump()`, one at a time — so your C code is + the host thread and run there during `calogPump()`, one at a time -- so your C code is never called concurrently and needs **no locking**. (An opt-in escape hatch runs a native inline on the script's thread when you want it.) - **Fire-and-forget scripts.** Scripts run on their own context threads; the host stays @@ -50,16 +50,17 @@ Swap `&calogJsEngine` for `&calogLuaEngine`, `&calogSquirrelEngine`, ## Engines -| Engine | Vtable | Extension | Notes | -|---------------|------------------------|-----------|-----------------------------------------| -| Lua 5.4 | `calogLuaEngine` | `.lua` | | -| JavaScript | `calogJsEngine` | `.js` | QuickJS-ng (ES2023+, BigInt → int64) | -| Squirrel 3.2 | `calogSquirrelEngine` | `.nut` | C++ VM | -| MY-BASIC | `calogMyBasicEngine` | `.bas` | interpreters serialize at load | -| Scheme | `calogS7Engine` | `.scm` | s7; 64-bit ints | -| Wren | `calogWrenEngine` | `.wren` | doubles only; call via `Calog.call(…)` | -| Berry | `calogBerryEngine` | `.be` | scalars + callbacks | +| Engine | Vtable | Extension | Notes | +|---------------|------------------------|-----------|-------------------------------------------| +| Lua 5.4 | `calogLuaEngine` | `.lua` | | +| JavaScript | `calogJsEngine` | `.js` | QuickJS-ng (ES2023+, BigInt -> int64) | +| Squirrel 3.2 | `calogSquirrelEngine` | `.nut` | C++ VM | +| MY-BASIC | `calogMyBasicEngine` | `.bas` | interpreters serialize at load | +| Scheme | `calogS7Engine` | `.scm` | s7; 64-bit ints | +| Wren | `calogWrenEngine` | `.wren` | doubles only; call via `Calog.call(...)` | +| Berry | `calogBerryEngine` | `.be` | scalars + callbacks | | Ruby | `calogMrubyEngine` | `.rb` | mruby; 64-bit ints; built by mruby's Rake | +| Tcl | `calogTclEngine` | `.tcl` | Tcl 9; 64-bit ints; string-typed values | A native can return a keyed `CalogValueT` record and **every** engine reads its fields with native syntax (`user.name`, `user["name"]`, `(user "name")`), and a script can hand a @@ -87,7 +88,7 @@ self-contained. ### Linking your program -Link against `lib/libcalog.a` plus the archive for **each engine you actually use** — +Link against `lib/libcalog.a` plus the archive for **each engine you actually use** -- unused engines (and their vendored runtimes) stay out of your binary. ```sh @@ -251,7 +252,7 @@ for (;;) { } ``` -Script results come back by **calling natives** — `calogContextEval` doesn't return a +Script results come back by **calling natives** -- `calogContextEval` doesn't return a value. Script errors are delivered to an optional handler on the host thread during `calogPump`: @@ -264,7 +265,7 @@ calogSetErrorHandler(calog, onError, NULL); // default logs to stderr ### Callbacks: script functions as values -A script can pass you a function. Keep it (retain), call it later, release it when done — +A script can pass you a function. Keep it (retain), call it later, release it when done -- calog runs the call on the engine that owns it and returns the result to you: ```c @@ -318,7 +319,7 @@ CalogContextT *ctx = calogContextLoad(calog, "config"); // tries config.lua, th ``` Or let the build decide which engines exist. Compile the calling file with -`-DCALOG_WITH_LUA -DCALOG_WITH_JS …` and call the header-inline helper — it registers +`-DCALOG_WITH_LUA -DCALOG_WITH_JS ...` and call the header-inline helper -- it registers exactly the engines you linked, and references no others: ```c @@ -330,7 +331,7 @@ CalogContextT *ctx = calogContextLoad(calog, "config"); A `CalogT` is a self-contained runtime; you can create several in one process. Each is driven by a host thread, and one thread may drive several by pumping each in turn. Keep -values and callbacks within a single runtime — they don't cross between runtimes. +values and callbacks within a single runtime -- they don't cross between runtimes. --- @@ -381,7 +382,7 @@ uint64_t calogCurrentId(void); // 0 on the host thread CalogT *calogCurrent(void); ``` -Statuses are `CalogStatusE` (`calogOkE`, `calogErrArgE`, `calogErrOomE`, …); `calogOkE` +Statuses are `CalogStatusE` (`calogOkE`, `calogErrArgE`, `calogErrOomE`, ...); `calogOkE` is 0. --- @@ -405,7 +406,7 @@ is happy on all kernels. src/ core (broker, values, actor) + one subdir per engine (lua, js, squirrel, mybasic) calog.h the entire public API tests/ the test programs -examples/ embed.c — a minimal host +examples/ embed.c -- a minimal host vendor/ vendored engine sources, built from source design.md the full design rationale and internals ``` @@ -419,5 +420,5 @@ build system. ## License calog is released under the [MIT License](LICENSE.md). The vendored engines (Lua, -Duktape, Squirrel, MY-BASIC) each retain their own MIT licenses — see +Duktape, Squirrel, MY-BASIC) each retain their own MIT licenses -- see [`LICENSE.md`](LICENSE.md) for the third-party notices. diff --git a/design.md b/design.md index f39add55..7f30b86f 100644 --- a/design.md +++ b/design.md @@ -1078,3 +1078,48 @@ adapter/engine/actor code (like `tsanlibs` with Lua); each VM is single-threaded cross-thread lambda callback, the error handler, three concurrent `mrb_state`s), ASan-clean; `tsanmruby` clean; cross-engine both ways (Ruby calling a Lua export, Lua invoking a Ruby lambda export); `make test` 29/29. + +## 20. Tcl -- the ninth engine (Tool Command Language) + +**Tcl** (`.tcl`, `calogTclEngine`) is the second engine whose static library is produced by the +engine's own build rather than compiled from vendored `.c`: Tcl 9.0.4's autoconf (`configure +--disable-shared`, out of tree into `vendor/tcl/build/`) emits `libtcl9.0.a` with no host deps beyond +a C toolchain -- Tcl bundles its own zlib fallback and libtommath. Two build facts mattered: `make +libtcl9.0.a` pulls in the zipfs library-embed step, so `vendor/tcl/library/` must be present +(over-trimming it broke the build); and calog never calls `Tcl_Init`, because the whole core language +(`proc`/`if`/`expr`/`string`/`list`/`dict`/...) is C built-ins registered by `Tcl_CreateInterp` -- so +the on-disk script library (init.tcl) is not needed. Linked footprint is ~2 MB. + +Concurrency is the reason Tcl was chosen: its apartment model -- one `Tcl_Interp` per thread, no +global interpreter lock -- IS calog's actor model. Each context creates its interp on its own thread +and never shares it; the one process-global init (`Tcl_FindExecutable` + caching the internal-rep type +pointers) runs once under `pthread_once`, and each context thread runs `Tcl_FinalizeThread` at +teardown. Natives are Tcl commands bound to one trampoline (the name is `objv[0]`, the context rides +on per-interp assoc data), so `cryptoUuid` is callable bare. + +The value model is the interesting part. Tcl is "everything is a string", so egress cannot read the +canonical type off a bare value: `tclToValue` dispatches on the `Tcl_Obj` internal representation +(`typePtr`, cached by minting a sample of each -- `Tcl_GetObjType` returns NULL for "int"/"bytearray" +in 9.0) for int64 (`Tcl_WideInt`), double, Tcl list <-> list, and Tcl dict <-> map. For a value with a +string (or no) rep it applies Tcl's own coercion -- a pure integer/real string becomes a number, so +`enetHost 8080` works -- otherwise a string. The documented EIAS losses: nil has no Tcl analogue and +round-trips to the empty string, and bool round-trips to 0/1. Binary-safe strings map to byte-array +objects (`Tcl_NewByteArrayObj`), since Tcl's string rep is UTF-8, not NUL-safe. + +Callbacks cross both ways on commands, with no custom `Tcl_ObjType`. A foreign `CalogFnT` (in +`tclFromValue`) or a Tcl command prefix wrapped by the adapter's `calogCallback` command both become a +`calogFn` command whose objProc is `tclForeignCmd` and whose clientData is the `CalogFnT` (released +by the command's delete proc -- Tcl commands carry per-registration data, unlike mruby's `mrb_func_t`). +The command NAME is the value the script holds -- it calls `$fn a b` -- and `tclToValue` recognizes +such a name (`Tcl_GetCommandInfo` -> objProc == `tclForeignCmd`) to marshal it back OUT as a function +value, so a Tcl callback reaches `psSubscribe`/`timerAfter`/`calogExport`. Bare-name exports work via +Tcl's own `unknown` handler (also normally from init.tcl): the adapter defines it to resolve an +undefined command against the export registry and invoke it -- and because Tcl has no receiver-method +syntax, `unknown` firing always means a genuinely-missing command, so no guard is needed (unlike Ruby's +`method_missing`). puts/print write to stdout directly (Tcl's channel `puts` needs the IO subsystem +calog does not init); there is no file/socket IO -- scripts use calog's `fs*`/`net*` natives. + +**Verified**: `testEngineTcl` (13 checks -- natives, dict egress/ingress with a nested list, a foreign +command callable, a cross-thread Tcl callback via `calogCallback`, the error handler, three concurrent +interpreters), ASan-clean; `tsantcl` clean; bare-name exports and cross-engine both ways; `make test` +30/30. diff --git a/examples/scripts/README.md b/examples/scripts/README.md index 1ac16fa3..86ff0fea 100644 --- a/examples/scripts/README.md +++ b/examples/scripts/README.md @@ -34,6 +34,7 @@ Conventions every example follows: | `mybasic.bas` | my-basic: variables, a `FOR..NEXT` sum, `IF..THEN..ELSE`, plus crypto + kv | | `berry.be` | Berry (Python-like): a `def`, a list built with a `for`, a map, then json + uuid | | `ruby.rb` | Ruby (mruby): a Range, `reduce` with a block, `select(&:even?)`, a Hash, then json + sha256 | +| `tcl.tcl` | Tcl 9: `set`/`expr`, a `foreach`, a list and a `dict`, then json + sha256 | | `scheme.scm` | s7 Scheme: a recursive factorial, list build + map, string ops (all in one `(begin ...)`) | | `wren.wren` | Wren: a class, a `List`, and every native reached via `Calog.call(name, [args])` | diff --git a/examples/scripts/languages/tcl.tcl b/examples/scripts/languages/tcl.tcl new file mode 100644 index 00000000..fd75c9fc --- /dev/null +++ b/examples/scripts/languages/tcl.tcl @@ -0,0 +1,20 @@ +# A guided tour of Tcl (9.0) running on calog. +# Demonstrates: set/expr, a foreach loop, a list and a dict, then the jsonStringify/jsonParse and +# cryptoHashSha256 natives. puts works; real file/socket IO is provided by calog's fs*/net* natives +# (not Tcl channels), so scripts stay uniform. Tcl values are strings, so a numeric literal handed +# to a native is coerced to an int. +# run: bin/calog examples/scripts/languages/tcl.tcl + +set nums {1 2 3 4 5} +set total 0 +foreach n $nums { set total [expr {$total + $n}] } +puts "nums = $nums, total = $total" + +set user [dict create name ada age 36] +puts "user as JSON: [jsonStringify $user]" + +set parsed [jsonParse {{"lang":"tcl","ints":[10,20,30]}}] +puts "parsed lang = [dict get $parsed lang], second int = [lindex [dict get $parsed ints] 1]" +puts "sha256(calog) = [cryptoHashSha256 calog]" + +calogExit 0 diff --git a/libs/calogExport.h b/libs/calogExport.h index a7e7389b..c6e033fb 100644 --- a/libs/calogExport.h +++ b/libs/calogExport.h @@ -13,9 +13,10 @@ // the same way via Kernel#method_missing, but only at TOP LEVEL (self is the main object, so a // missing method on some other receiver -- obj.foo -- is never hijacked). my-basic likewise // bare-resolves a name called like a function, but CASE-INSENSITIVELY (it uppercases identifiers -// at parse time), so `luaExample(1, 2)` there matches the export ignoring case. Wren and Berry -// resolve names statically and use calogCall('luaExample', ...). Resolution is dynamic: a name -// exported at any time becomes callable immediately, and calogUnexport takes effect at once. +// at parse time), so `luaExample(1, 2)` there matches the export ignoring case. Tcl resolves a bare +// command the same way via its `unknown` handler (`luaExample 1 2`). Wren and Berry resolve names +// statically and use calogCall('luaExample', ...). Resolution is dynamic: a name exported at any +// time becomes callable immediately, and calogUnexport takes effect at once. // // An exported function is an ordinary calog function value, so a call runs in the exporter's // own context/thread (marshalled like any callable), and a call after the exporter is gone diff --git a/libs/calogTask.c b/libs/calogTask.c index 3ee5a59e..15d53bef 100644 --- a/libs/calogTask.c +++ b/libs/calogTask.c @@ -72,6 +72,9 @@ static const TaskEngineT gTaskEngines[] = { #endif #ifdef CALOG_WITH_MRUBY { "mruby", &calogMrubyEngine }, +#endif +#ifdef CALOG_WITH_TCL + { "tcl", &calogTclEngine }, #endif { NULL, NULL } }; diff --git a/src/calog.h b/src/calog.h index 458279f5..5b39ad18 100644 --- a/src/calog.h +++ b/src/calog.h @@ -204,6 +204,7 @@ extern const CalogEngineT calogBerryEngine; extern const CalogEngineT calogS7Engine; extern const CalogEngineT calogWrenEngine; extern const CalogEngineT calogMrubyEngine; +extern const CalogEngineT calogTclEngine; // Register the built-in engines selected at build time, so calogContextLoad works // without hand-registering each. Define CALOG_WITH_LUA / _JS / _SQUIRREL / _MYBASIC (in @@ -235,6 +236,9 @@ static inline void calogRegisterBuiltinEngines(CalogT *calog) { #endif #ifdef CALOG_WITH_MRUBY calogRegisterEngine(calog, &calogMrubyEngine); +#endif +#ifdef CALOG_WITH_TCL + calogRegisterEngine(calog, &calogTclEngine); #endif (void)calog; // no-op if the build selected no engines } diff --git a/src/calogMain.c b/src/calogMain.c index 14d837d8..73d7af82 100644 --- a/src/calogMain.c +++ b/src/calogMain.c @@ -94,7 +94,8 @@ static const CalogEngineT *const gEngines[] = { &calogBerryEngine, &calogS7Engine, &calogWrenEngine, - &calogMrubyEngine + &calogMrubyEngine, + &calogTclEngine }; // The built-in libraries, in registration order. One source of truth: main() registers every diff --git a/src/tcl/tclAdapter.c b/src/tcl/tclAdapter.c new file mode 100644 index 00000000..5a0beccc --- /dev/null +++ b/src/tcl/tclAdapter.c @@ -0,0 +1,718 @@ +// tclAdapter.c -- Tcl (Tool Command Language) engine adapter for the broker. +// +// Each exposed native is a Tcl command bound to one shared trampoline (tclTrampoline): the command +// name is objv[0], the owning context rides on per-interp assoc data (tclOf), and the arguments +// dispatch through calogCall. Marshalling covers scalars and BINARY-SAFE strings (via byte-array +// objects); aggregates cross both ways (Tcl list<->list, Tcl dict<->map). Because Tcl is +// "everything is a string", egress (tclToValue) recovers the canonical type from the Tcl_Obj +// internal representation (typePtr, cached at first use), coercing an untyped pure-numeric string +// to int/real and otherwise keeping it a string; nil has no Tcl analogue and round-trips to the +// empty string, bool to 0/1 (documented EIAS losses). +// +// Callbacks both ways ride on commands. A foreign CalogFnT (in tclFromValue, or a Tcl command +// prefix wrapped by the `calogCallback` command) becomes a "calogFn" command whose objProc is +// tclForeignCmd and whose clientData is the CalogFnT (released by its delete proc). The command +// NAME is the value the script holds -- call it `$fn a b` -- and tclToValue recognizes such a name +// (Tcl_GetCommandInfo -> objProc == tclForeignCmd) to marshal it back OUT as a function value, so a +// Tcl callback reaches natives like psSubscribe/timerAfter/calogExport. There is no file/socket IO; +// scripts use calog's fs*/net* natives, and the adapter provides puts/print. +// +// Error model: a failed native/marshal sets the interp result and returns TCL_ERROR (Tcl unwinds). +// Concurrency: Tcl's apartment model gives one Tcl_Interp per thread with no global lock; the one +// process-global init (Tcl_FindExecutable + caching the type pointers) is done once via pthread_once, +// and each context thread runs Tcl_FinalizeThread at teardown. + +#define _POSIX_C_SOURCE 200809L + +#include "tclAdapter.h" + +#include + +#include +#include +#include +#include +#include + +struct CalogTclT { + Tcl_Interp *interp; + CalogT *broker; + uint64_t ctxId; + int32_t nextFn; // mints unique "calogFn" command names for function values +}; + +// Backs a CalogFnT that invokes a Tcl command prefix (a script callback captured as a value). +typedef struct TclScriptT { + CalogTclT *context; + Tcl_Obj *prefix; +} TclScriptT; + +// Internal-rep type pointers, cached once (they are process-global static ObjTypes in libtcl). +// Tcl_GetObjType returns NULL for "int"/"bytearray" in 9.0, so we mint a sample of each instead. +static pthread_once_t gInitOnce = PTHREAD_ONCE_INIT; +static const Tcl_ObjType *gIntType = NULL; +static const Tcl_ObjType *gDoubleType = NULL; +static const Tcl_ObjType *gByteArrayType = NULL; +static const Tcl_ObjType *gListType = NULL; +static const Tcl_ObjType *gDictType = NULL; + +static int tclCallbackCmd(void *cd, Tcl_Interp *ip, int objc, Tcl_Obj *const objv[]); +static int tclForeignCmd(void *cd, Tcl_Interp *ip, int objc, Tcl_Obj *const objv[]); +static void tclForeignDelete(void *cd); +static int32_t tclFromValue(CalogTclT *context, const CalogValueT *value, Tcl_Obj **out, int32_t depth); +static void tclInitOnce(void); +static int32_t tclMakeFnCommand(CalogTclT *context, CalogFnT *fn, Tcl_Obj **out); +static int32_t tclMarshalArgs(CalogTclT *context, int objc, Tcl_Obj *const objv[], int from, CalogValueT **out, int32_t *outCount); +static CalogTclT *tclOf(Tcl_Interp *ip); +static int tclPrintCmd(void *cd, Tcl_Interp *ip, int objc, Tcl_Obj *const objv[]); +static int tclPutsCmd(void *cd, Tcl_Interp *ip, int objc, Tcl_Obj *const objv[]); +static int32_t tclScriptInvoke(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData); +static void tclScriptRelease(CalogFnT *callable); +static int tclSetResult(CalogTclT *context, Tcl_Interp *ip, int32_t status, CalogValueT *result); +static int32_t tclToValue(CalogTclT *context, Tcl_Obj *obj, CalogValueT *out, int32_t depth); +static int tclTrampoline(void *cd, Tcl_Interp *ip, int objc, Tcl_Obj *const objv[]); +static int tclUnknownCmd(void *cd, Tcl_Interp *ip, int objc, Tcl_Obj *const objv[]); +static int32_t tclWrapCommand(CalogTclT *context, Tcl_Obj *prefix, CalogFnT **out); + + +int32_t calogTclCreate(CalogTclT **out, CalogT *broker, uint64_t ctxId) { + CalogTclT *context; + + *out = NULL; + pthread_once(&gInitOnce, tclInitOnce); + context = (CalogTclT *)calloc(1, sizeof(*context)); + if (context == NULL) { + return calogErrOomE; + } + context->interp = Tcl_CreateInterp(); + if (context->interp == NULL) { + free(context); + return calogErrOomE; + } + context->broker = broker; + context->ctxId = ctxId; + Tcl_SetAssocData(context->interp, "calogCtx", NULL, context); // recovered by tclOf + // puts/print write to stdout directly: Tcl's channel-based puts needs the IO subsystem calog + // does not initialize. calogCallback wraps a command prefix into a callable function value. + Tcl_CreateObjCommand(context->interp, "puts", tclPutsCmd, NULL, NULL); + Tcl_CreateObjCommand(context->interp, "print", tclPrintCmd, NULL, NULL); + Tcl_CreateObjCommand(context->interp, "calogCallback", tclCallbackCmd, NULL, NULL); + // Bare-name export resolution: an undefined command resolves to a broker export (like the hook + // engines). Tcl's `unknown` command-not-found handler normally lives in the skipped init.tcl. + Tcl_CreateObjCommand(context->interp, "unknown", tclUnknownCmd, NULL, NULL); + *out = context; + return calogOkE; +} + + +// calogCallback command ?arg ...? -- wrap a Tcl command prefix as a calog function value (its name). +static int tclCallbackCmd(void *cd, Tcl_Interp *ip, int objc, Tcl_Obj *const objv[]) { + CalogTclT *context; + Tcl_Obj *prefix; + Tcl_Obj *nameObj; + CalogFnT *fn; + + (void)cd; + context = tclOf(ip); + if (objc < 2) { + Tcl_WrongNumArgs(ip, 1, objv, "command ?arg ...?"); + return TCL_ERROR; + } + prefix = Tcl_NewListObj(objc - 1, objv + 1); + if (tclWrapCommand(context, prefix, &fn) != calogOkE) { + Tcl_BounceRefCount(prefix); + Tcl_SetObjResult(ip, Tcl_NewStringObj("calogCallback: out of memory", -1)); + return TCL_ERROR; + } + if (tclMakeFnCommand(context, fn, &nameObj) != calogOkE) { + calogFnRelease(fn); + Tcl_SetObjResult(ip, Tcl_NewStringObj("calogCallback: out of memory", -1)); + return TCL_ERROR; + } + calogFnRelease(fn); // tclMakeFnCommand retained its own reference for the command + Tcl_SetObjResult(ip, nameObj); + return TCL_OK; +} + + +void calogTclDestroy(CalogTclT *context) { + if (context == NULL) { + return; + } + if (context->interp != NULL) { + Tcl_DeleteInterp(context->interp); // fires every function-value command's delete proc + } + // Each calog context owns its thread, so this is thread teardown: release Tcl's per-thread + // notifier / thread storage. + Tcl_FinalizeThread(); + free(context); +} + + +int32_t calogTclExport(CalogTclT *context, const char *name, CalogFnT **out) { + Tcl_CmdInfo info; + Tcl_Obj *nameObj; + Tcl_Obj *prefix; + + *out = NULL; + if (!Tcl_GetCommandInfo(context->interp, name, &info)) { + return calogErrNotFoundE; + } + nameObj = Tcl_NewStringObj(name, -1); + prefix = Tcl_NewListObj(1, &nameObj); + return tclWrapCommand(context, prefix, out); +} + + +int32_t calogTclExpose(CalogTclT *context, const char *name) { + if (calogLookup(context->broker, name) == NULL) { + return calogErrNotFoundE; + } + Tcl_CreateObjCommand(context->interp, name, tclTrampoline, NULL, NULL); + return calogOkE; +} + + +// Call target for a function value (a foreign CalogFnT, or a Tcl callback wrapped by calogCallback). +static int tclForeignCmd(void *cd, Tcl_Interp *ip, int objc, Tcl_Obj *const objv[]) { + CalogTclT *context; + CalogValueT *args; + CalogValueT result; + int32_t argc; + int32_t index; + int32_t status; + + context = tclOf(ip); + args = NULL; + argc = 0; + if (tclMarshalArgs(context, objc, objv, 1, &args, &argc) != calogOkE) { + Tcl_SetObjResult(ip, Tcl_NewStringObj("failed to marshal a function-value argument", -1)); + return TCL_ERROR; + } + status = calogFnInvoke((CalogFnT *)cd, args, argc, &result); + for (index = 0; index < argc; index++) { + calogValueFree(&args[index]); + } + free(args); + return tclSetResult(context, ip, status, &result); +} + + +static void tclForeignDelete(void *cd) { + calogFnRelease((CalogFnT *)cd); +} + + +static int32_t tclFromValue(CalogTclT *context, const CalogValueT *value, Tcl_Obj **out, int32_t depth) { + *out = NULL; + if (depth >= CALOG_MAX_DEPTH) { + *out = Tcl_NewObj(); + return calogErrDepthE; + } + switch (value->type) { + case calogNilE: + *out = Tcl_NewObj(); // Tcl has no nil; empty string + return calogOkE; + case calogBoolE: + *out = Tcl_NewWideIntObj(value->as.b ? 1 : 0); + return calogOkE; + case calogIntE: + *out = Tcl_NewWideIntObj((Tcl_WideInt)value->as.i); + return calogOkE; + case calogRealE: + *out = Tcl_NewDoubleObj((double)value->as.r); + return calogOkE; + case calogStringE: + // byte array -> binary-safe (Tcl string reps are UTF-8, not NUL-safe) + *out = Tcl_NewByteArrayObj((const unsigned char *)value->as.s.bytes, (Tcl_Size)value->as.s.length); + return calogOkE; + case calogAggE: { + CalogAggT *aggregate; + int64_t index; + int32_t status; + Tcl_Obj *child; + aggregate = value->as.agg; + if (calogAggIsKeyed(aggregate)) { + Tcl_Obj *dict; + dict = Tcl_NewDictObj(); + for (index = 0; index < aggregate->arrayCount; index++) { + status = tclFromValue(context, &aggregate->array[index], &child, depth + 1); + if (status != calogOkE) { + Tcl_BounceRefCount(dict); + *out = Tcl_NewObj(); + return status; + } + Tcl_DictObjPut(NULL, dict, Tcl_NewWideIntObj((Tcl_WideInt)index), child); + } + for (index = 0; index < aggregate->pairCount; index++) { + Tcl_Obj *key; + status = tclFromValue(context, &aggregate->pairs[index].key, &key, depth + 1); + if (status != calogOkE) { + Tcl_BounceRefCount(dict); + *out = Tcl_NewObj(); + return status; + } + status = tclFromValue(context, &aggregate->pairs[index].value, &child, depth + 1); + if (status != calogOkE) { + Tcl_BounceRefCount(key); + Tcl_BounceRefCount(dict); + *out = Tcl_NewObj(); + return status; + } + Tcl_DictObjPut(NULL, dict, key, child); + } + *out = dict; + return calogOkE; + } + Tcl_Obj *list; + list = Tcl_NewListObj(0, NULL); + for (index = 0; index < aggregate->arrayCount; index++) { + status = tclFromValue(context, &aggregate->array[index], &child, depth + 1); + if (status != calogOkE) { + Tcl_BounceRefCount(list); + *out = Tcl_NewObj(); + return status; + } + Tcl_ListObjAppendElement(NULL, list, child); + } + *out = list; + return calogOkE; + } + case calogFnE: + return tclMakeFnCommand(context, value->as.fn, out); + } + *out = Tcl_NewObj(); + return calogErrTypeE; +} + + +static void tclInitOnce(void) { + Tcl_Obj *sample; + + Tcl_FindExecutable(NULL); // one-time subsystem (encoding/stub) init + + sample = Tcl_NewWideIntObj(0); + Tcl_IncrRefCount(sample); gIntType = sample->typePtr; Tcl_DecrRefCount(sample); + sample = Tcl_NewDoubleObj(0.0); + Tcl_IncrRefCount(sample); gDoubleType = sample->typePtr; Tcl_DecrRefCount(sample); + sample = Tcl_NewByteArrayObj((const unsigned char *)"\0", 1); + Tcl_IncrRefCount(sample); gByteArrayType = sample->typePtr; Tcl_DecrRefCount(sample); + sample = Tcl_NewListObj(0, NULL); + Tcl_ListObjAppendElement(NULL, sample, Tcl_NewWideIntObj(0)); + Tcl_IncrRefCount(sample); gListType = sample->typePtr; Tcl_DecrRefCount(sample); + sample = Tcl_NewDictObj(); + Tcl_DictObjPut(NULL, sample, Tcl_NewStringObj("k", 1), Tcl_NewWideIntObj(0)); + Tcl_IncrRefCount(sample); gDictType = sample->typePtr; Tcl_DecrRefCount(sample); +} + + +// Register a "calogFn" command backed by `fn` (retained; released by tclForeignDelete). The +// command NAME is returned as the script-visible function value. +static int32_t tclMakeFnCommand(CalogTclT *context, CalogFnT *fn, Tcl_Obj **out) { + char name[32]; + + snprintf(name, sizeof(name), "calogFn%d", context->nextFn++); + calogFnRetain(fn); + Tcl_CreateObjCommand(context->interp, name, tclForeignCmd, fn, tclForeignDelete); + *out = Tcl_NewStringObj(name, -1); + return calogOkE; +} + + +static int32_t tclMarshalArgs(CalogTclT *context, int objc, Tcl_Obj *const objv[], int from, CalogValueT **out, int32_t *outCount) { + CalogValueT *args; + int32_t argc; + int32_t index; + int32_t status; + + *out = NULL; + *outCount = 0; + argc = (int32_t)objc - from; + if (argc <= 0) { + return calogOkE; + } + args = (CalogValueT *)calloc((size_t)argc, sizeof(CalogValueT)); + if (args == NULL) { + return calogErrOomE; + } + for (index = 0; index < argc; index++) { + status = tclToValue(context, objv[from + index], &args[index], 0); + if (status != calogOkE) { + int32_t cleanup; + for (cleanup = 0; cleanup < index; cleanup++) { + calogValueFree(&args[cleanup]); + } + free(args); + return status; + } + } + *out = args; + *outCount = argc; + return calogOkE; +} + + +static CalogTclT *tclOf(Tcl_Interp *ip) { + return (CalogTclT *)Tcl_GetAssocData(ip, "calogCtx", NULL); +} + + +static int tclPrintCmd(void *cd, Tcl_Interp *ip, int objc, Tcl_Obj *const objv[]) { + int index; + + (void)cd; + (void)ip; + for (index = 1; index < objc; index++) { + Tcl_Size len; + const char *bytes; + bytes = Tcl_GetStringFromObj(objv[index], &len); + fwrite(bytes, 1, (size_t)len, stdout); + } + return TCL_OK; +} + + +static int tclPutsCmd(void *cd, Tcl_Interp *ip, int objc, Tcl_Obj *const objv[]) { + int nonewline; + int first; + Tcl_Size len; + const char *bytes; + + (void)cd; + (void)ip; + nonewline = (objc >= 2 && strcmp(Tcl_GetString(objv[1]), "-nonewline") == 0); + first = nonewline ? 2 : 1; + // The string is the last argument; a channel argument (e.g. stdout) before it is ignored. + if (objc > first) { + bytes = Tcl_GetStringFromObj(objv[objc - 1], &len); + fwrite(bytes, 1, (size_t)len, stdout); + } + if (!nonewline) { + fputc('\n', stdout); + } + return TCL_OK; +} + + +static int32_t tclScriptInvoke(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) { + TclScriptT *holder; + CalogTclT *context; + Tcl_Interp *ip; + Tcl_Size prefixCount; + Tcl_Obj **prefixElems; + Tcl_Obj **objv; + int32_t total; + int32_t index; + int32_t status; + int code; + + holder = (TclScriptT *)userData; + context = holder->context; + ip = context->interp; + calogValueNil(result); + if (Tcl_ListObjGetElements(ip, holder->prefix, &prefixCount, &prefixElems) != TCL_OK) { + return calogFail(result, calogErrArgE, "invalid tcl callback prefix"); + } + total = (int32_t)prefixCount + argCount; + objv = (Tcl_Obj **)calloc((size_t)(total > 0 ? total : 1), sizeof(Tcl_Obj *)); + if (objv == NULL) { + return calogFail(result, calogErrOomE, "out of memory invoking tcl callback"); + } + for (index = 0; index < (int32_t)prefixCount; index++) { + objv[index] = prefixElems[index]; + Tcl_IncrRefCount(objv[index]); + } + for (index = 0; index < argCount; index++) { + Tcl_Obj *arg; + status = tclFromValue(context, &args[index], &arg, 0); + if (status != calogOkE) { + int32_t cleanup; + Tcl_BounceRefCount(arg); + for (cleanup = 0; cleanup < (int32_t)prefixCount + index; cleanup++) { + Tcl_DecrRefCount(objv[cleanup]); + } + free(objv); + return calogFail(result, status, "failed to marshal a tcl callback argument"); + } + objv[(int32_t)prefixCount + index] = arg; + Tcl_IncrRefCount(arg); + } + code = Tcl_EvalObjv(ip, total, objv, 0); + for (index = 0; index < total; index++) { + Tcl_DecrRefCount(objv[index]); + } + free(objv); + if (code != TCL_OK) { + return calogFail(result, calogErrArgE, Tcl_GetString(Tcl_GetObjResult(ip))); + } + return tclToValue(context, Tcl_GetObjResult(ip), result, 0); +} + + +static void tclScriptRelease(CalogFnT *callable) { + TclScriptT *holder; + + holder = (TclScriptT *)calogFnUserData(callable); + Tcl_DecrRefCount(holder->prefix); + free(holder); +} + + +static int tclSetResult(CalogTclT *context, Tcl_Interp *ip, int32_t status, CalogValueT *result) { + Tcl_Obj *obj; + int32_t marshal; + + if (status != calogOkE) { + Tcl_SetObjResult(ip, Tcl_NewStringObj((result->type == calogStringE) ? result->as.s.bytes : "native call failed", -1)); + calogValueFree(result); + return TCL_ERROR; + } + marshal = tclFromValue(context, result, &obj, 0); + calogValueFree(result); + if (marshal != calogOkE) { + Tcl_SetObjResult(ip, Tcl_NewStringObj("failed to marshal the native result", -1)); + return TCL_ERROR; + } + Tcl_SetObjResult(ip, obj); + return TCL_OK; +} + + +static int32_t tclToValue(CalogTclT *context, Tcl_Obj *obj, CalogValueT *out, int32_t depth) { + const Tcl_ObjType *type; + + calogValueNil(out); + if (depth >= CALOG_MAX_DEPTH) { + return calogErrDepthE; + } + type = obj->typePtr; + if (type == gDictType) { + CalogAggT *aggregate; + Tcl_DictSearch search; + Tcl_Obj *key; + Tcl_Obj *val; + int done; + int32_t status; + status = calogAggCreate(&aggregate, calogMapE); + if (status != calogOkE) { + return status; + } + if (Tcl_DictObjFirst(NULL, obj, &search, &key, &val, &done) != TCL_OK) { + calogAggFree(aggregate); + return calogErrArgE; + } + for (; !done; Tcl_DictObjNext(&search, &key, &val, &done)) { + CalogValueT ckey; + CalogValueT cval; + status = tclToValue(context, key, &ckey, depth + 1); + if (status != calogOkE) { + Tcl_DictObjDone(&search); + calogAggFree(aggregate); + return status; + } + status = tclToValue(context, val, &cval, depth + 1); + if (status != calogOkE) { + calogValueFree(&ckey); + Tcl_DictObjDone(&search); + calogAggFree(aggregate); + return status; + } + status = calogAggSet(aggregate, &ckey, &cval); + if (status != calogOkE) { + calogValueFree(&ckey); + calogValueFree(&cval); + Tcl_DictObjDone(&search); + calogAggFree(aggregate); + return status; + } + } + Tcl_DictObjDone(&search); + calogValueAgg(out, aggregate); + return calogOkE; + } + if (type == gListType) { + CalogAggT *aggregate; + Tcl_Size count; + Tcl_Obj **elems; + Tcl_Size index; + int32_t status; + if (Tcl_ListObjGetElements(NULL, obj, &count, &elems) != TCL_OK) { + return calogErrArgE; + } + status = calogAggCreate(&aggregate, calogListE); + if (status != calogOkE) { + return status; + } + for (index = 0; index < count; index++) { + CalogValueT element; + status = tclToValue(context, elems[index], &element, depth + 1); + if (status != calogOkE) { + calogAggFree(aggregate); + return status; + } + status = calogAggPush(aggregate, &element); + if (status != calogOkE) { + calogValueFree(&element); + calogAggFree(aggregate); + return status; + } + } + calogValueAgg(out, aggregate); + return calogOkE; + } + if (type == gIntType) { + Tcl_WideInt wide; + Tcl_GetWideIntFromObj(NULL, obj, &wide); + calogValueInt(out, (int64_t)wide); + return calogOkE; + } + if (type == gDoubleType) { + double real; + Tcl_GetDoubleFromObj(NULL, obj, &real); + calogValueReal(out, real); + return calogOkE; + } + if (type == gByteArrayType) { + Tcl_Size length; + unsigned char *bytes; + bytes = Tcl_GetByteArrayFromObj(obj, &length); + return calogValueString(out, (const char *)bytes, (int64_t)length); + } + // String or no internal representation. + { + Tcl_Size length; + const char *bytes; + Tcl_WideInt wide; + double real; + bytes = Tcl_GetStringFromObj(obj, &length); + // A function-value command name marshals back OUT as a function value. + if (length >= 7 && memcmp(bytes, "calogFn", 7) == 0) { + Tcl_CmdInfo info; + if (Tcl_GetCommandInfo(context->interp, bytes, &info) && info.objProc == tclForeignCmd) { + calogFnRetain((CalogFnT *)info.objClientData); + calogValueFn(out, (CalogFnT *)info.objClientData); + return calogOkE; + } + } + // Tcl's own coercion: a pure integer/real string is a number. + if (Tcl_GetWideIntFromObj(NULL, obj, &wide) == TCL_OK) { + calogValueInt(out, (int64_t)wide); + return calogOkE; + } + if (Tcl_GetDoubleFromObj(NULL, obj, &real) == TCL_OK) { + calogValueReal(out, real); + return calogOkE; + } + return calogValueString(out, bytes, (int64_t)length); + } +} + + +static int tclTrampoline(void *cd, Tcl_Interp *ip, int objc, Tcl_Obj *const objv[]) { + CalogTclT *context; + CalogValueT *args; + CalogValueT result; + int32_t argc; + int32_t index; + int32_t status; + + (void)cd; + context = tclOf(ip); + args = NULL; + argc = 0; + if (tclMarshalArgs(context, objc, objv, 1, &args, &argc) != calogOkE) { + Tcl_SetObjResult(ip, Tcl_NewStringObj("failed to marshal a native argument", -1)); + return TCL_ERROR; + } + status = calogCall(context->broker, Tcl_GetString(objv[0]), args, argc, &result); + for (index = 0; index < argc; index++) { + calogValueFree(&args[index]); + } + free(args); + return tclSetResult(context, ip, status, &result); +} + + +// The `unknown` handler: a command Tcl could not resolve -- objv[1] is its name, objv[2..] its +// arguments -- is looked up as a broker export and invoked; a miss becomes the standard error. +// Tcl is case-sensitive, so the match is exact (unlike my-basic). No receiver-method syntax exists +// in Tcl, so no top-level guard is needed (unlike Ruby's method_missing). +static int tclUnknownCmd(void *cd, Tcl_Interp *ip, int objc, Tcl_Obj *const objv[]) { + CalogTclT *context; + const char *name; + CalogValueT nameArg; + CalogValueT resolved; + CalogValueT *args; + CalogValueT result; + int32_t argc; + int32_t index; + int32_t status; + + (void)cd; + context = tclOf(ip); + if (objc < 2) { + Tcl_SetObjResult(ip, Tcl_NewStringObj("unknown: missing command name", -1)); + return TCL_ERROR; + } + name = Tcl_GetString(objv[1]); + calogValueNil(&resolved); + if (calogValueString(&nameArg, name, (int64_t)strlen(name)) == calogOkE) { + calogCall(context->broker, "__calogExportResolve", &nameArg, 1, &resolved); + calogValueFree(&nameArg); + } + if (resolved.type != calogFnE) { + calogValueFree(&resolved); + Tcl_SetObjResult(ip, Tcl_ObjPrintf("invalid command name \"%s\"", name)); + return TCL_ERROR; + } + // It is an export: invoke with the remaining words. Keep the resolved reference across the + // invoke (guards a concurrent unexport), then release it before returning. + args = NULL; + argc = 0; + if (tclMarshalArgs(context, objc, objv, 2, &args, &argc) != calogOkE) { + calogValueFree(&resolved); + Tcl_SetObjResult(ip, Tcl_NewStringObj("failed to marshal a native argument", -1)); + return TCL_ERROR; + } + status = calogFnInvoke(resolved.as.fn, args, argc, &result); + for (index = 0; index < argc; index++) { + calogValueFree(&args[index]); + } + free(args); + calogValueFree(&resolved); + return tclSetResult(context, ip, status, &result); +} + + +static int32_t tclWrapCommand(CalogTclT *context, Tcl_Obj *prefix, CalogFnT **out) { + TclScriptT *holder; + int32_t status; + + *out = NULL; + holder = (TclScriptT *)malloc(sizeof(*holder)); + if (holder == NULL) { + return calogErrOomE; + } + holder->context = context; + holder->prefix = prefix; + Tcl_IncrRefCount(prefix); + status = calogFnCreate(out, context->broker, tclScriptInvoke, holder, tclScriptRelease, context->ctxId); + if (status != calogOkE) { + Tcl_DecrRefCount(prefix); + free(holder); + return status; + } + return calogOkE; +} + + +int32_t calogTclRun(CalogTclT *context, const char *source) { + int code; + + code = Tcl_EvalEx(context->interp, source, -1, TCL_EVAL_GLOBAL); + if (code != TCL_OK) { + fprintf(stderr, "tcl error: %s\n", Tcl_GetString(Tcl_GetObjResult(context->interp))); + return calogErrArgE; + } + return calogOkE; +} diff --git a/src/tcl/tclAdapter.h b/src/tcl/tclAdapter.h new file mode 100644 index 00000000..5cfc623b --- /dev/null +++ b/src/tcl/tclAdapter.h @@ -0,0 +1,31 @@ +// tclAdapter.h -- Tcl (Tool Command Language) engine adapter for the broker. +// +// Exposes broker-registered natives into a Tcl interpreter as commands routed through one +// trampoline (the command name is objv[0], the context is per-interp assoc data). Marshals values +// between Tcl_Obj and CalogValueT: int64 (Tcl_WideInt), double, list<->list, dict<->map, and +// BINARY-SAFE strings via byte-array objects. Tcl is "everything is a string", so egress recovers +// the canonical type from the Tcl_Obj internal representation (typePtr), coercing an untyped +// numeric string to int/real and otherwise treating it as a string; nil has no Tcl equivalent and +// round-trips to the empty string, and bool round-trips to 0/1 (documented EIAS losses). +// +// Callbacks both ways ride on commands: a foreign CalogFnT pushed IN becomes a command (carrying +// the CalogFnT as clientData, released by its delete proc) whose NAME is the value handed to the +// script (call it as `$fn a b`); a Tcl command prefix wrapped with `calogCallback` becomes a +// CalogFnT the same way, so it marshals back OUT as a function value (tclToValue recognizes such a +// command by its trampoline). Tcl file/socket IO is intentionally absent -- scripts use calog's +// fs*/net* natives; the adapter provides puts/print. + +#ifndef TCL_ADAPTER_H +#define TCL_ADAPTER_H + +#include "calogInternal.h" + +typedef struct CalogTclT CalogTclT; + +int32_t calogTclCreate(CalogTclT **out, CalogT *broker, uint64_t ctxId); +void calogTclDestroy(CalogTclT *context); +int32_t calogTclExport(CalogTclT *context, const char *name, CalogFnT **out); +int32_t calogTclExpose(CalogTclT *context, const char *name); +int32_t calogTclRun(CalogTclT *context, const char *source); + +#endif diff --git a/src/tcl/tclEngine.c b/src/tcl/tclEngine.c new file mode 100644 index 00000000..cecf69bd --- /dev/null +++ b/src/tcl/tclEngine.c @@ -0,0 +1,62 @@ +// tclEngine.c -- bridges the Tcl adapter to the actor layer's CalogEngineT vtable. +// +// Every hook runs on the owning context's thread (createInterpreter, runSource, +// destroyInterpreter), confining the Tcl interpreter to one thread -- which is exactly Tcl's +// apartment threading model (one Tcl_Interp per thread, no global lock). createInterpreter builds +// the interp and exposes the registered natives; runSource evaluates a script and reports failure +// through the single error channel (result). + +#include "calogInternal.h" +#include "tclAdapter.h" + +static int32_t tclEngineCreate(CalogContextT *context, void **interpOut); +static void tclEngineDestroy(void *interp); +static int32_t tclEngineRun(void *interp, const char *source, CalogValueT *result); +static void tclExposeVisitor(const CalogEntryT *entry, void *ud); + +static const char *const tclExtensions[] = { "tcl", NULL }; + +const CalogEngineT calogTclEngine = { + "tcl", + tclExtensions, + tclEngineCreate, + tclEngineDestroy, + tclEngineRun +}; + + +static int32_t tclEngineCreate(CalogContextT *context, void **interpOut) { + CalogTclT *tcl; + int32_t status; + + *interpOut = NULL; + status = calogTclCreate(&tcl, calogContextBroker(context), calogContextId(context)); + if (status != calogOkE) { + return status; + } + calogForEach(calogContextBroker(context), tclExposeVisitor, tcl); + *interpOut = tcl; + return calogOkE; +} + + +static void tclEngineDestroy(void *interp) { + calogTclDestroy((CalogTclT *)interp); +} + + +static int32_t tclEngineRun(void *interp, const char *source, CalogValueT *result) { + int32_t status; + + calogValueNil(result); + status = calogTclRun((CalogTclT *)interp, source); + if (status != calogOkE) { + return calogFail(result, status, "tcl script failed"); + } + return calogOkE; +} + + +static void tclExposeVisitor(const CalogEntryT *entry, void *ud) { + calogTclExpose((CalogTclT *)ud, entry->name); +} diff --git a/tests/testEngineTcl.c b/tests/testEngineTcl.c new file mode 100644 index 00000000..521aadbc --- /dev/null +++ b/tests/testEngineTcl.c @@ -0,0 +1,402 @@ +// testEngineTcl.c -- Tcl on a context thread, driven the host way: register natives, open a +// context, fire-and-forget a script, and calogPump on the host thread. Verifies host-thread +// dispatch, the inline escape hatch, the cross-thread callback, aggregates both ways (list/dict), +// a foreign function value, the error handler, and concurrent contexts (Tcl apartment threading). + +#define _POSIX_C_SOURCE 200809L + +#include "calog.h" + +#include +#include +#include +#include +#include + +#define CHECK(cond, msg) checkImpl((cond), (msg), __FILE__, __LINE__) + +#define PUMP_LIMIT 4000 + +static CalogT *calog = NULL; +static _Atomic int64_t reportedValue = 0; +static _Atomic uint64_t reportedCtxId = 0xFFFFu; +static _Atomic uint64_t inlineCtxId = 0xFFFFu; +static _Atomic int32_t bumpCount = 0; +static _Atomic bool scriptDone = false; +static _Atomic int32_t errorCount = 0; +static _Atomic uint64_t errorCtxId = 0; +static CalogFnT *_Atomic storedCb = NULL; +static char storedName[32] = { 0 }; +static _Atomic int32_t nameLen = -1; +static int32_t testsRun = 0; +static int32_t testsFailed = 0; + +static void checkImpl(bool condition, const char *message, const char *file, int32_t line); +static int32_t nativeAdd(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData); +static int32_t nativeBump(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData); +static int32_t nativeDone(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData); +static int32_t nativeGetAdder(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData); +static int32_t nativeMakeUser(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData); +static int32_t nativeMapAge(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData); +static int32_t nativeReport(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData); +static int32_t nativeReportInline(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData); +static int32_t nativeReportName(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData); +static int32_t nativeSetCb(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData); +static void onError(uint64_t contextId, const char *message, void *userData); +static void pumpUntilDone(void); +static void testConcurrentContexts(void); +static void testCrossThreadCallback(void); +static void testForeignFunction(void); +static void testHostAndInlineNatives(void); +static void testMapIngress(void); +static void testMaterializedRecord(void); +static void testScriptError(void); + + +static void checkImpl(bool condition, const char *message, const char *file, int32_t line) { + testsRun++; + if (!condition) { + testsFailed++; + printf("FAIL %s:%d %s\n", file, line, message); + } +} + + +static int32_t nativeAdd(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) { + (void)userData; + calogValueNil(result); + if (argCount != 2 || args[0].type != calogIntE || args[1].type != calogIntE) { + return calogFail(result, calogErrArgE, "add expects two integers"); + } + calogValueInt(result, args[0].as.i + args[1].as.i); + return calogOkE; +} + + +static int32_t nativeBump(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) { + (void)args; + (void)argCount; + (void)userData; + atomic_fetch_add(&bumpCount, 1); + calogValueNil(result); + return calogOkE; +} + + +static int32_t nativeDone(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) { + (void)args; + (void)argCount; + (void)userData; + atomic_store(&scriptDone, true); + calogValueNil(result); + return calogOkE; +} + + +static int32_t nativeGetAdder(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) { + CalogFnT *callable; + int32_t status; + + (void)args; + (void)argCount; + (void)userData; + calogValueNil(result); + status = calogFnFromNative(&callable, calog, nativeAdd, NULL); + if (status != calogOkE) { + return calogFail(result, status, "getAdder could not allocate"); + } + calogValueFn(result, callable); + return calogOkE; +} + + +static int32_t nativeMakeUser(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) { + CalogAggT *user; + CalogValueT key; + CalogValueT val; + int32_t status; + + (void)args; + (void)argCount; + (void)userData; + calogValueNil(result); + status = calogAggCreate(&user, calogMapE); + if (status != calogOkE) { + return calogFail(result, status, "makeUser could not allocate"); + } + calogValueString(&key, "name", 4); + calogValueString(&val, "ada", 3); + calogAggSet(user, &key, &val); + calogValueString(&key, "age", 3); + calogValueInt(&val, 36); + calogAggSet(user, &key, &val); + calogValueAgg(result, user); + return calogOkE; +} + + +static int32_t nativeMapAge(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) { + CalogValueT key; + CalogValueT *found; + + (void)userData; + calogValueNil(result); + if (argCount != 1 || args[0].type != calogAggE) { + return calogFail(result, calogErrArgE, "mapAge expects a map"); + } + calogValueString(&key, "age", 3); + found = calogAggGet(args[0].as.agg, &key); + calogValueFree(&key); + if (found != NULL && found->type == calogIntE) { + atomic_store(&reportedValue, found->as.i); + } + return calogOkE; +} + + +static int32_t nativeReport(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) { + (void)userData; + calogValueNil(result); + if (argCount != 1 || args[0].type != calogIntE) { + return calogFail(result, calogErrArgE, "report expects one integer"); + } + atomic_store(&reportedCtxId, calogCurrentId()); + atomic_store(&reportedValue, args[0].as.i); + return calogOkE; +} + + +static int32_t nativeReportInline(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) { + (void)args; + (void)argCount; + (void)userData; + atomic_store(&inlineCtxId, calogCurrentId()); + calogValueNil(result); + return calogOkE; +} + + +static int32_t nativeReportName(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) { + size_t length; + + (void)userData; + calogValueNil(result); + if (argCount != 1 || args[0].type != calogStringE) { + return calogFail(result, calogErrArgE, "reportName expects one string"); + } + length = (size_t)args[0].as.s.length; + if (length >= sizeof(storedName)) { + length = sizeof(storedName) - 1; + } + memcpy(storedName, args[0].as.s.bytes, length); + storedName[length] = '\0'; + atomic_store(&nameLen, (int32_t)length); + return calogOkE; +} + + +static int32_t nativeSetCb(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) { + (void)userData; + calogValueNil(result); + if (argCount != 1 || args[0].type != calogFnE) { + return calogFail(result, calogErrArgE, "setCb expects one function"); + } + calogFnRetain(args[0].as.fn); + atomic_store(&storedCb, args[0].as.fn); + return calogOkE; +} + + +static void onError(uint64_t contextId, const char *message, void *userData) { + (void)message; + (void)userData; + atomic_store(&errorCtxId, contextId); + atomic_fetch_add(&errorCount, 1); +} + + +static void pumpUntilDone(void) { + struct timespec ts = { 0, 500000 }; + int errorsBefore; + int i; + + errorsBefore = atomic_load(&errorCount); + for (i = 0; i < PUMP_LIMIT; i++) { + calogPump(calog); + if (atomic_load(&scriptDone) || atomic_load(&errorCount) != errorsBefore) { + calogPump(calog); + return; + } + nanosleep(&ts, NULL); + } +} + + +static void testHostAndInlineNatives(void) { + CalogContextT *ctx; + + ctx = calogContextOpen(calog, &calogTclEngine); + CHECK(ctx != NULL, "opened a Tcl context"); + + atomic_store(&scriptDone, false); + calogContextEval(ctx, "report 42\nreportInline 1\ndone"); + pumpUntilDone(); + + CHECK(atomic_load(&reportedValue) == 42, "host native received the argument"); + CHECK(atomic_load(&reportedCtxId) == 0, "default native ran on the host thread (id 0)"); + CHECK(atomic_load(&inlineCtxId) == calogContextId(ctx), "inline native ran on the script's own thread"); + + calogContextClose(ctx); +} + + +static void testMaterializedRecord(void) { + CalogContextT *ctx; + + ctx = calogContextOpen(calog, &calogTclEngine); + atomic_store(&scriptDone, false); + atomic_store(&nameLen, -1); + atomic_store(&reportedValue, 0); + calogContextEval(ctx, "set u [makeUser]\nreport [dict get $u age]\nreportName [dict get $u name]\ndone"); + pumpUntilDone(); + + CHECK(atomic_load(&reportedValue) == 36, "read an int field from a materialized record dict"); + CHECK(atomic_load(&nameLen) == 3 && memcmp(storedName, "ada", 3) == 0, "read a string field from a materialized record dict"); + + calogContextClose(ctx); +} + + +static void testMapIngress(void) { + CalogContextT *ctx; + + ctx = calogContextOpen(calog, &calogTclEngine); + atomic_store(&scriptDone, false); + atomic_store(&reportedValue, 0); + // The script builds a dict (with a nested list, exercising list ingress too) and hands it + // to a native, which reads a field. + calogContextEval(ctx, "set m [dict create age 9 tags [list 1 2]]\nmapAge $m\ndone"); + pumpUntilDone(); + + CHECK(atomic_load(&reportedValue) == 9, "native read a field from a dict the script built"); + + calogContextClose(ctx); +} + + +static void testForeignFunction(void) { + CalogContextT *ctx; + + ctx = calogContextOpen(calog, &calogTclEngine); + atomic_store(&scriptDone, false); + atomic_store(&reportedValue, 0); + // getAdder returns a function value (a command name); the script calls it as `$adder 2 3`. + calogContextEval(ctx, "set adder [getAdder]\nreport [$adder 2 3]\ndone"); + pumpUntilDone(); + + CHECK(atomic_load(&reportedValue) == 5, "script called a foreign function value pushed in from the host"); + + calogContextClose(ctx); +} + + +static void testCrossThreadCallback(void) { + CalogContextT *ctx; + CalogFnT *callback; + CalogValueT arg; + CalogValueT result; + int32_t status; + + ctx = calogContextOpen(calog, &calogTclEngine); + atomic_store(&scriptDone, false); + atomic_store(&storedCb, NULL); + // A Tcl proc wrapped by calogCallback becomes a function value that marshals to a CalogFnT. + calogContextEval(ctx, "proc cb {x} { expr {$x + 100} }\nsetCb [calogCallback cb]\ndone"); + pumpUntilDone(); + + callback = atomic_load(&storedCb); + CHECK(callback != NULL, "a Tcl callback was captured as a CalogFnT"); + + calogValueInt(&arg, 7); + status = calogFnInvoke(callback, &arg, 1, &result); + CHECK(status == calogOkE && result.type == calogIntE && result.as.i == 107, "cross-thread callable invoke routed to the owner"); + calogValueFree(&result); + calogValueFree(&arg); + calogFnRelease(callback); + + calogContextClose(ctx); +} + + +static void testScriptError(void) { + CalogContextT *ctx; + int32_t before; + + ctx = calogContextOpen(calog, &calogTclEngine); + before = atomic_load(&errorCount); + atomic_store(&scriptDone, false); + calogContextEval(ctx, "error {intentional test error}"); + pumpUntilDone(); + + CHECK(atomic_load(&errorCount) == before + 1, "a fire-and-forget script error reached the error handler"); + CHECK(atomic_load(&errorCtxId) == calogContextId(ctx), "the error names the failing context"); + + calogContextClose(ctx); +} + + +static void testConcurrentContexts(void) { + CalogContextT *ctxs[3]; + struct timespec ts = { 0, 500000 }; + int32_t i; + + atomic_store(&bumpCount, 0); + for (i = 0; i < 3; i++) { + ctxs[i] = calogContextOpen(calog, &calogTclEngine); + calogContextEval(ctxs[i], "bump\nbump\nbump"); + } + for (i = 0; i < PUMP_LIMIT && atomic_load(&bumpCount) < 9; i++) { + calogPump(calog); + nanosleep(&ts, NULL); + } + CHECK(atomic_load(&bumpCount) == 9, "three concurrent Tcl contexts all dispatched to the host thread"); + for (i = 0; i < 3; i++) { + calogContextClose(ctxs[i]); + } +} + + +int main(void) { + calog = calogCreate(); + if (calog == NULL) { + printf("calog create failed\n"); + return 1; + } + calogSetErrorHandler(calog, onError, NULL); + calogRegister(calog, "report", nativeReport, NULL); + calogRegister(calog, "setCb", nativeSetCb, NULL); + calogRegister(calog, "done", nativeDone, NULL); + calogRegister(calog, "bump", nativeBump, NULL); + calogRegister(calog, "makeUser", nativeMakeUser, NULL); + calogRegister(calog, "reportName", nativeReportName, NULL); + calogRegister(calog, "getAdder", nativeGetAdder, NULL); + calogRegister(calog, "mapAge", nativeMapAge, NULL); + calogRegisterInline(calog, "reportInline", nativeReportInline, NULL); + + testHostAndInlineNatives(); + testMaterializedRecord(); + testMapIngress(); + testForeignFunction(); + testCrossThreadCallback(); + testScriptError(); + testConcurrentContexts(); + + calogDestroy(calog); + + printf("\n%d checks, %d failed\n", testsRun, testsFailed); + fflush(stdout); + if (testsFailed != 0) { + return 1; + } + return 0; +} diff --git a/vendor/tcl/.github/workflows/linux-build.yml b/vendor/tcl/.github/workflows/linux-build.yml new file mode 100644 index 00000000..62e88fa5 --- /dev/null +++ b/vendor/tcl/.github/workflows/linux-build.yml @@ -0,0 +1,105 @@ +name: Linux +on: + push: + branches: + - "main" + - "core-9-0-branch" + tags: + - "core-*" +permissions: + contents: read +jobs: + plan: + runs-on: ubuntu-latest + outputs: + gcc: ${{ steps.matrix.outputs.gcc }} + steps: + - name: Select build matrix based on branch name + id: matrix + run: | + ( + echo gcc=$(jq -nc '{config: (if env.IsMatched == "true" then env.FULL else env.PARTIAL end) | fromjson }' ) + ) | tee -a $GITHUB_OUTPUT + env: + IsMatched: ${{ github.ref_name == 'main' || github.ref_name == 'core-9-0-branch' }} + # DO NOT CHANGE THESE MATRIX SPECS; IT AFFECTS OUR COST CONTROLS + FULL: > + [ + "", + "CFLAGS=-DTCL_NO_DEPRECATED=1", + "--disable-shared", + "--disable-zipfs", + "--enable-symbols", + "--enable-symbols=mem", + "--enable-symbols=all", + "CFLAGS=-ftrapv", + "CFLAGS=-m32 CPPFLAGS=-m32 LDFLAGS=-m32 --disable-64bit" + ] + PARTIAL: > + [ + "", + "--enable-symbols=all", + "CFLAGS=-m32 CPPFLAGS=-m32 LDFLAGS=-m32 --disable-64bit" + ] + gcc: + needs: plan + runs-on: ubuntu-24.04 + strategy: + matrix: ${{ fromJson(needs.plan.outputs.gcc) }} + defaults: + run: + shell: bash + working-directory: unix + steps: + - name: Checkout + uses: actions/checkout@v7 + timeout-minutes: 5 + - name: Install 32-bit dependencies if needed + # Duplicated from above + if: ${{ matrix.config == 'CFLAGS=-m32 CPPFLAGS=-m32 LDFLAGS=-m32 --disable-64bit' }} + run: | + sudo apt-get update + sudo apt-get install gcc-multilib libc6-dev-i386 + - name: Prepare + run: | + touch tclStubInit.c tclOOStubInit.c tclOOScript.h + working-directory: generic + - name: Configure ${{ matrix.config }} + run: | + mkdir "${HOME}/install dir" + ./configure ${CFGOPT} "--prefix=$HOME/install dir" || (cat config.log && exit 1) + env: + CFGOPT: ${{ matrix.config }} + timeout-minutes: 5 + - name: Build + run: | + make -j4 all + timeout-minutes: 5 + - name: Build Test Harness + run: | + make -j4 tcltest + timeout-minutes: 5 + - name: Info + run: | + ulimit -a || echo 'get limit failed' + make runtest SCRIPT=../.github/workflows/info.tcl || echo 'get info failed' + - name: Run Tests + run: | + make test + env: + ERROR_ON_FAILURES: 1 + timeout-minutes: 30 + - name: Test-Drive Installation + run: | + make install + timeout-minutes: 5 + - name: Create Distribution Package + if: ${{ matrix.config == '' }} + run: | + make dist + timeout-minutes: 5 + - name: Convert Documentation to HTML + if: ${{ matrix.config == '' }} + run: | + make html-tcl + timeout-minutes: 5 diff --git a/vendor/tcl/.github/workflows/mac-build.yml b/vendor/tcl/.github/workflows/mac-build.yml new file mode 100644 index 00000000..85ea1835 --- /dev/null +++ b/vendor/tcl/.github/workflows/mac-build.yml @@ -0,0 +1,106 @@ +name: macOS +on: + push: + branches: + - "main" + - "core-9-0-branch" + tags: + - "core-*" +permissions: + contents: read +jobs: + plan: + runs-on: ubuntu-latest + outputs: + clang: ${{ steps.matrix.outputs.clang }} + steps: + - name: Select build matrix based on branch name + id: matrix + run: | + ( + echo clang=$(jq -nc '{config: (if env.IsMatched == "true" then env.FULL else env.PARTIAL end) | fromjson }' ) + ) | tee -a $GITHUB_OUTPUT + env: + IsMatched: ${{ github.ref_name == 'main' || github.ref_name == 'core-9-0-branch' }} + # DO NOT CHANGE THIS MATRIX SPEC; IT AFFECTS OUR COST CONTROLS + FULL: > + [ + "", + "--disable-shared", + "--disable-zipfs", + "--enable-symbols", + "--enable-symbols=mem", + "--enable-symbols=all" + ] + PARTIAL: > + [ + "", + "--enable-symbols=all" + ] + xcode: + runs-on: macos-15 + defaults: + run: + shell: bash + working-directory: macosx + steps: + - name: Checkout + uses: actions/checkout@v7 + timeout-minutes: 5 + - name: Prepare + run: | + touch tclStubInit.c tclOOStubInit.c tclOOScript.h + working-directory: generic + - name: Build + run: make -j4 all + env: + CFLAGS: -arch x86_64 -arch arm64 + timeout-minutes: 15 + - name: Run Tests + run: make -j4 test styles=develop + env: + ERROR_ON_FAILURES: 1 + MAC_CI: 1 + timeout-minutes: 15 + clang: + runs-on: macos-15 + needs: plan + strategy: + matrix: ${{ fromJson(needs.plan.outputs.clang) }} + defaults: + run: + shell: bash + working-directory: unix + steps: + - name: Checkout + uses: actions/checkout@v7 + timeout-minutes: 5 + - name: Prepare + run: | + touch tclStubInit.c tclOOStubInit.c tclOOScript.h + mkdir "$HOME/install dir" + working-directory: generic + - name: Configure ${{ matrix.config }} + # Note that macOS is always a 64 bit platform + run: ./configure --enable-dtrace --enable-framework ${CFGOPT} "--prefix=$HOME/install" || (cat config.log && exit 1) + env: + CFLAGS: -arch x86_64 -arch arm64 + CFGOPT: ${{ matrix.config }} + timeout-minutes: 5 + - name: Build + run: | + make -j4 all tcltest + env: + CFLAGS: -arch x86_64 -arch arm64 + timeout-minutes: 15 + - name: Info + run: | + ulimit -a || echo 'get limit failed' + make runtest SCRIPT=../.github/workflows/info.tcl || echo 'get info failed' + - name: Run Tests + run: | + make test + env: + ERROR_ON_FAILURES: 1 + MAC_CI: 1 + timeout-minutes: 20 diff --git a/vendor/tcl/.github/workflows/onefiledist.yml b/vendor/tcl/.github/workflows/onefiledist.yml new file mode 100644 index 00000000..c2827e7e --- /dev/null +++ b/vendor/tcl/.github/workflows/onefiledist.yml @@ -0,0 +1,243 @@ +name: Build Binaries +on: + push: + branches: + - "main" + - "core-9-0-branch" + tags: + - "core-*" +permissions: + contents: read +jobs: + linux: + name: Linux + runs-on: ubuntu-24.04 + defaults: + run: + shell: bash + timeout-minutes: 10 + steps: + - name: Checkout + uses: actions/checkout@v7 + - name: Prepare + run: | + touch generic/tclStubInit.c generic/tclOOStubInit.c + mkdir 1dist + echo "VER_PATH=$(cd tools; pwd)/addVerToFile.tcl" >> $GITHUB_ENV + working-directory: . + - name: Configure + run: ./configure --disable-symbols --disable-shared --enable-zipfs + working-directory: unix + - name: Build + run: | + make tclsh + make shell SCRIPT="$VER_PATH $GITHUB_ENV" + echo "TCL_ZIP=`pwd`/`echo libtcl*.zip`" >> $GITHUB_ENV + working-directory: unix + - name: Package + run: | + cp ../unix/tclsh tclsh${TCL_PATCHLEVEL}_snapshot + chmod +x tclsh${TCL_PATCHLEVEL}_snapshot + tar -cf tclsh${TCL_PATCHLEVEL}_snapshot.tar tclsh${TCL_PATCHLEVEL}_snapshot + working-directory: 1dist + - name: Info + run: | + ulimit -a || echo 'get limit failed' + echo 'puts exe:\t[info nameofexecutable]\nver:\t[info patchlevel]\t[if {![catch tcl::build-info ret]} {set ret}]\nlib:\t[info library]\nplat:\t[lsort -dictionary -stride 2 [array get tcl_platform]]' | make runtest || echo 'get info failed' + - name: Upload + uses: actions/upload-artifact@v7 + with: + name: Tclsh ${{ env.TCL_PATCHLEVEL }} Linux single-file build (snapshot) + path: 1dist/*.tar + id: upload + outputs: + url: ${{ steps.upload.outputs.artifact-url }} + macos: + name: macOS + runs-on: macos-15-intel + defaults: + run: + shell: bash + timeout-minutes: 10 + steps: + - name: Checkout + uses: actions/checkout@v7 + - name: Checkout create-dmg + uses: actions/checkout@v7 + with: + repository: create-dmg/create-dmg + ref: v1.2.2 + path: create-dmg + - name: Prepare + run: | + mkdir 1dist + touch generic/tclStubInit.c generic/tclOOStubInit.c || true + wget https://github.com/culler/macher/releases/download/v1.8/macher + sudo cp macher /usr/local/bin + sudo chmod a+x /usr/local/bin/macher + echo "VER_PATH=$(cd tools; pwd)/addVerToFile.tcl" >> $GITHUB_ENV + echo "CREATE_DMG=$(cd create-dmg;pwd)/create-dmg" >> $GITHUB_ENV + echo "CFLAGS=-arch x86_64 -arch arm64" >> $GITHUB_ENV + - name: Configure + run: ./configure --disable-symbols --disable-shared --enable-zipfs + working-directory: unix + - name: Build + run: | + make -j4 tclsh + make -j4 shell SCRIPT="$VER_PATH $GITHUB_ENV" + echo "TCL_BIN=`pwd`/tclsh" >> $GITHUB_ENV + echo "TCL_ZIP=`pwd`/`echo libtcl*.zip`" >> $GITHUB_ENV + working-directory: unix + - name: Package + run: | + mkdir contents + cp $TCL_BIN contents/tclsh${TCL_PATCHLEVEL}_snapshot + chmod +x contents/tclsh${TCL_PATCHLEVEL}_snapshot + cat > contents/README.txt <> $GITHUB_ENV + mkdir 1dist + working-directory: . + - name: Configure + run: ./configure $CFGOPT + working-directory: win + - name: Build + run: | + make binaries libraries + echo "TCL_ZIP=`pwd`/`echo libtcl*.zip`" >> $GITHUB_ENV + working-directory: win + - name: Get Exact Version + run: | + ./tclsh*.exe $VER_PATH $GITHUB_ENV + working-directory: win + - name: Set Executable Name + run: | + cp ../win/tclsh*.exe tclsh${TCL_PATCHLEVEL}_snapshot.exe + working-directory: 1dist + - name: Info + run: | + ulimit -a || echo 'get limit failed' + echo 'puts exe:\t[info nameofexecutable]\nver:\t[info patchlevel]\t[if {![catch tcl::build-info ret]} {set ret}]\nlib:\t[info library]\nplat:\t[lsort -dictionary -stride 2 [array get tcl_platform]]' | make runtest || echo 'get info failed' + - name: Upload + uses: actions/upload-artifact@v7 + with: + name: Tclsh ${{ env.TCL_PATCHLEVEL }} Windows single-file build (snapshot) + path: '1dist/*_snapshot.exe' + id: upload + outputs: + url: ${{ steps.upload.outputs.artifact-url }} + combine: + needs: + - linux + - macos + - win + name: Combine Artifacts (prototype) + runs-on: ubuntu-latest + defaults: + run: + shell: bash + timeout-minutes: 10 + env: + # See also + # https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables + REMOTE_PATH: ${{ vars.PUBLISH_DROP_PATH }}/data-${{ github.sha }} + steps: + - name: Make directory + run: | + mkdir data + - name: Get Linux build + uses: actions/download-artifact@v8 + with: + path: data + # Can't download by artifact ID; stupid missing feature! + merge-multiple: true + - name: Check data downloaded + run: | + ls -AlR + working-directory: data + - name: Transfer built files + # https://github.com/marketplace/actions/rsync-deployments-action + uses: burnett01/rsync-deployments@8.0.5 + id: rsync + if: false # Disabled... for now + with: + # I don't know what the right switches are here, BTW + switches: -avzr + path: data/ + remote_path: ${{ env.REMOTE_PATH }} + remote_host: ${{ vars.PUBLISH_HOST }} + remote_user: ${{ vars.PUBLISH_USER }} + remote_key: ${{ secrets.DEPLOY_HOST_KEY }} + # MUST be a literal passwordless key + - name: Publish files + # https://github.com/marketplace/actions/ssh-remote-commands + uses: appleboy/ssh-action@v1.2.5 + id: ssh + if: steps.rsync.outcome == 'success' + with: + host: ${{ vars.PUBLISH_HOST }} + username: ${{ vars.PUBLISH_USER }} + key: ${{ secrets.DEPLOY_HOST_KEY }} + script: | + ${{ vars.PUBLISHER_SCRIPT }} ${{ env.REMOTE_PATH }} ${{ github.ref_type }} ${{ github.ref_name }} + - name: Report what would be done + if: steps.rsync.outcome == 'skipped' + env: + SWITCHES: -av + LOCAL_PATH: data/ + REMOTE_HOST: ${{ vars.PUBLISH_HOST }} + REMOTE_USER: ${{ vars.PUBLISH_USER }} + REMOTE_SCRIPT: | + ${{ vars.PUBLISHER_SCRIPT }} ${{ env.REMOTE_PATH }} ${{ github.ref_type }} ${{ github.ref_name }} + run: | + echo "would run: rsync $SWITCHES $LOCAL_PATH $REMOTE_USER@$REMOTE_HOST:$REMOTE_PATH" + echo "would run: ssh $REMOTE_USER@$REMOTE_HOST $REMOTE_SCRIPT" + # Consider https://github.com/marketplace/actions/slack-notify maybe? diff --git a/vendor/tcl/.github/workflows/win-build.yml b/vendor/tcl/.github/workflows/win-build.yml new file mode 100644 index 00000000..59a13ce9 --- /dev/null +++ b/vendor/tcl/.github/workflows/win-build.yml @@ -0,0 +1,148 @@ +name: Windows +on: + push: + branches: + - "main" + - "core-9-0-branch" + tags: + - "core-*" +permissions: + contents: read +jobs: + plan: + runs-on: ubuntu-latest + outputs: + msvc: ${{ steps.matrix.outputs.msvc }} + gcc: ${{ steps.matrix.outputs.gcc }} + steps: + - name: Select build matrix based on branch name + id: matrix + run: | + ( + echo msvc=$(jq -nc '{config: (if env.IsMatched == "true" then env.MSVC_FULL else env.MSVC_PARTIAL end) | fromjson }' ) + echo gcc=$(jq -nc '{config: (if env.IsMatched == "true" then env.GCC_FULL else env.GCC_PARTIAL end) | fromjson }' ) + ) | tee -a $GITHUB_OUTPUT + env: + IsMatched: ${{ github.ref_name == 'main' || github.ref_name == 'core-9-0-branch' }} + # DO NOT CHANGE THESE MATRIX SPECS; IT AFFECTS OUR COST CONTROLS + MSVC_FULL: > + [ + "", + "CHECKS=nodep", + "OPTS=static", + "OPTS=noembed", + "OPTS=symbols", + "OPTS=symbols STATS=compdbg,memdbg" + ] + MSVC_PARTIAL: > + [ + "", + "OPTS=symbols STATS=compdbg,memdbg" + ] + GCC_FULL: > + [ + "", + "CFLAGS=-DTCL_NO_DEPRECATED=1", + "--disable-shared", + "--disable-zipfs", + "--enable-symbols", + "--enable-symbols=mem", + "--enable-symbols=all" + ] + GCC_PARTIAL: > + [ + "", + "--disable-shared", + "--enable-symbols=all" + ] + msvc: + runs-on: windows-2025 + needs: plan + defaults: + run: + shell: powershell + working-directory: win + strategy: + matrix: ${{ fromJson(needs.plan.outputs.msvc) }} + # Using powershell means we need to explicitly stop on failure + steps: + - name: Checkout + uses: actions/checkout@v7 + timeout-minutes: 5 + - name: Init MSVC + uses: ilammy/msvc-dev-cmd@v1 + timeout-minutes: 5 + - name: Build ${{ matrix.config }} + run: | + &nmake -f makefile.vc ${{ matrix.config }} all + if ($lastexitcode -ne 0) { + throw "nmake exit code: $lastexitcode" + } + timeout-minutes: 5 + - name: Build Test Harness ${{ matrix.config }} + run: | + &nmake -f makefile.vc ${{ matrix.config }} tcltest + if ($lastexitcode -ne 0) { + throw "nmake exit code: $lastexitcode" + } + timeout-minutes: 5 + - name: Run Tests ${{ matrix.config }} + run: | + &nmake -f makefile.vc ${{ matrix.config }} test + if ($lastexitcode -ne 0) { + throw "nmake exit code: $lastexitcode" + } + timeout-minutes: 30 + env: + ERROR_ON_FAILURES: 1 + gcc: + runs-on: windows-2025 + needs: plan + defaults: + run: + shell: msys2 {0} + working-directory: win + strategy: + matrix: ${{ fromJson(needs.plan.outputs.gcc) }} + steps: + - name: Install MSYS2 + uses: msys2/setup-msys2@v2 + with: + msystem: MINGW64 + install: git mingw-w64-x86_64-toolchain make + timeout-minutes: 10 + - name: Checkout + uses: actions/checkout@v7 + timeout-minutes: 5 + - name: Prepare + run: | + touch tclStubInit.c tclOOStubInit.c tclOOScript.h + mkdir "${HOME}/install dir" + working-directory: generic + - name: Configure ${{ matrix.config }} + run: | + ./configure ${CFGOPT} "--prefix=$HOME/install dir" || (cat config.log && exit 1) + env: + CFGOPT: --enable-64bit ${{ matrix.config }} + timeout-minutes: 5 + - name: Build + run: make -j4 all + timeout-minutes: 5 + - name: Build Test Harness + run: make -j4 tcltest + timeout-minutes: 5 + - name: Info + run: | + ulimit -a || echo 'get limit failed' + make runtest SCRIPT=../.github/workflows/info.tcl || echo 'get info failed' + - name: Run Tests + run: make test + timeout-minutes: 30 + env: + ERROR_ON_FAILURES: 1 + - name: Install + run: make install + timeout-minutes: 5 + +# If you add builds with Wine, be sure to define the environment variable +# CI_USING_WINE when running them so that broken tests know not to run. diff --git a/vendor/tcl/README.md b/vendor/tcl/README.md new file mode 100644 index 00000000..32d9fc9f --- /dev/null +++ b/vendor/tcl/README.md @@ -0,0 +1,156 @@ +# README: Tcl + +This is the **Tcl 9.0.4** source distribution. + +You can get any source release of Tcl from [our distribution +site](https://sourceforge.net/projects/tcl/files/Tcl/). + +9.1 (in development, daily build) +[![Build Status](https://github.com/tcltk/tcl/actions/workflows/linux-build.yml/badge.svg?branch=main)](https://github.com/tcltk/tcl/actions/workflows/linux-build.yml?query=branch%3Amain) +[![Build Status](https://github.com/tcltk/tcl/actions/workflows/win-build.yml/badge.svg?branch=main)](https://github.com/tcltk/tcl/actions/workflows/win-build.yml?query=branch%3Amain) +[![Build Status](https://github.com/tcltk/tcl/actions/workflows/mac-build.yml/badge.svg?branch=main)](https://github.com/tcltk/tcl/actions/workflows/mac-build.yml?query=branch%3Amain) +
+9.0 (production release, daily build) +[![Build Status](https://github.com/tcltk/tcl/actions/workflows/linux-build.yml/badge.svg?branch=core-9-0-branch)](https://github.com/tcltk/tcl/actions/workflows/linux-build.yml?query=branch%3Acore-9-0-branch) +[![Build Status](https://github.com/tcltk/tcl/actions/workflows/win-build.yml/badge.svg?branch=core-9-0-branch)](https://github.com/tcltk/tcl/actions/workflows/win-build.yml?query=branch%3Acore-9-0-branch) +[![Build Status](https://github.com/tcltk/tcl/actions/workflows/mac-build.yml/badge.svg?branch=core-9-0-branch)](https://github.com/tcltk/tcl/actions/workflows/mac-build.yml?query=branch%3Acore-9-0-branch) + +## Contents + 1. [Introduction](#intro) + 2. [Documentation](#doc) + 3. [Compiling and installing Tcl](#build) + 4. [Development tools](#devtools) + 5. [Tcl newsgroup](#complangtcl) + 6. [The Tcler's Wiki](#wiki) + 7. [Mailing lists](#email) + 8. [Support and Training](#support) + 9. [Tracking Development](#watch) + 10. [Thank You](#thanks) + +## 1. Introduction +Tcl provides a powerful platform for creating integration applications that +tie together diverse applications, protocols, devices, and frameworks. +When paired with the Tk toolkit, Tcl provides the fastest and most powerful +way to create GUI applications that run on PCs, Unix, and macOS. +Tcl can also be used for a variety of web-related tasks and for creating +powerful command languages for applications. + +Tcl is maintained, enhanced, and distributed freely by the Tcl community. +Source code development and tracking of bug reports and feature requests +take place at [core.tcl-lang.org](https://core.tcl-lang.org/). +Tcl/Tk release and mailing list services are [hosted by +SourceForge](https://sourceforge.net/projects/tcl/) +with the Tcl Developer Xchange hosted at +[www.tcl-lang.org](https://www.tcl-lang.org). + +Tcl is a freely available open-source package. You can do virtually +anything you like with it, such as modifying it, redistributing it, +and selling it either in whole or in part. See the file +`license.terms` for complete information. + +## 2. Documentation +Extensive documentation is available on our website. +The home page for this release, including new features, is +[here](https://www.tcl-lang.org/software/tcltk/9.0.html). +Detailed release notes can be found at the +[file distributions page](https://sourceforge.net/projects/tcl/files/Tcl/) +by clicking on the relevant version. + +Information about Tcl itself can be found at the [Developer +Xchange](https://www.tcl-lang.org/about/). +There have been many Tcl books on the market. Many are mentioned in +[the Wiki](https://wiki.tcl-lang.org/_/ref?N=25206). + +The complete set of reference manual entries for Tcl 9.0 is [online, +here](https://www.tcl-lang.org/man/tcl9.0/). + +### 2a. Unix Documentation +The `doc` subdirectory in this release contains a complete set of +reference manual entries for Tcl. Files with extension "`.1`" are for +programs (for example, `tclsh.1`); files with extension "`.3`" are for C +library procedures; and files with extension "`.n`" describe Tcl +commands. The file "`doc/Tcl.n`" gives a quick summary of the Tcl +language syntax. To print any of the man pages on Unix, cd to the +"doc" directory and invoke your favorite variant of troff using the +normal -man macros, for example + + groff -man -Tpdf Tcl.n >output.pdf + +to print Tcl.n to PDF. If Tcl has been installed correctly and your "man" program +supports it, you should be able to access the Tcl manual entries using the +normal "man" mechanisms, such as + + man Tcl + +### 2b. Windows Documentation +The "doc" subdirectory in this release contains a complete set of Windows +help files for Tcl. Once you install this Tcl release, a shortcut to the +Windows help Tcl documentation will appear in the "Start" menu: + + Start | Programs | Tcl | Tcl Help + +## 3. Compiling and installing Tcl +There are brief notes in the `unix/README`, `win/README`, and `macosx/README` +about compiling on these different platforms. There is additional information +about building Tcl from sources +[online](https://www.tcl-lang.org/doc/howto/compile.html). + +## 4. Development tools +ActiveState produces a high-quality set of commercial quality development +tools that is available to accelerate your Tcl application development. +Tcl Dev Kit builds on the earlier TclPro toolset and provides a debugger, +static code checker, single-file wrapping utility, bytecode compiler, and +more. More information can be found at + + https://www.activestate.com/products/tcl/ + +## 5. Tcl newsgroup +There is a USENET newsgroup, "`comp.lang.tcl`", intended for the exchange of +information about Tcl, Tk, and related applications. The newsgroup is a +great place to ask general information questions. For bug reports, please +see the "Support and bug fixes" section below. + +## 6. Tcl'ers Wiki +There is a [wiki-based open community site](https://wiki.tcl-lang.org/) +covering all aspects of Tcl/Tk. + +It is dedicated to the Tcl programming language and its extensions. A +wealth of useful information can be found there. It contains code +snippets, references to papers, books, and FAQs, as well as pointers to +development tools, extensions, and applications. You can also recommend +additional URLs by editing the wiki yourself. + +## 7. Mailing lists +Several mailing lists are hosted at SourceForge to discuss development or use +issues (like Macintosh and Windows topics). For more information and to +subscribe, visit [here](https://sourceforge.net/projects/tcl/) and go to the +Mailing Lists page. + +## 8. Support and Training +We are very interested in receiving bug reports, patches, and suggestions for +improvements. We prefer that you send this information to us as tickets +entered into [our issue tracker](https://core.tcl-lang.org/tcl/reportlist). + +We will log and follow-up on each bug, although we cannot promise a +specific turn-around time. Enhancements may take longer and may not happen +at all unless there is widespread support for them (we're trying to +slow the rate at which Tcl/Tk turns into a kitchen sink). It's very +difficult to make incompatible changes to Tcl/Tk at this point, due to +the size of the installed base. + +The Tcl community is too large for us to provide much individual support for +users. If you need help we suggest that you post questions to `comp.lang.tcl` +or ask a question on [Stack +Overflow](https://stackoverflow.com/questions/tagged/tcl). We read the +newsgroup and will attempt to answer esoteric questions for which no one else +is likely to know the answer. In addition, see the wiki for [links to other +organizations](https://wiki.tcl-lang.org/training) that offer Tcl/Tk training. + +## 9. Tracking Development +Tcl is developed in public. You can keep an eye on how Tcl is changing at +[core.tcl-lang.org](https://core.tcl-lang.org/). + +## 10. Thank You +We'd like to express our thanks to the Tcl community for all the +helpful suggestions, bug reports, and patches we have received. +Tcl/Tk has improved vastly and will continue to do so with your help. diff --git a/vendor/tcl/changes.md b/vendor/tcl/changes.md new file mode 100644 index 00000000..4bf78dd7 --- /dev/null +++ b/vendor/tcl/changes.md @@ -0,0 +1,290 @@ + +The source code for Tcl is managed by fossil. Tcl developers coordinate all +changes to the Tcl source code at + +> [Tcl Source Code](https://core.tcl-lang.org/tcl/timeline) + +Release Tcl 9.0.4 arises from the check-in with tag `core-9-0-4`. + +Tcl patch releases have the primary purpose of delivering bug fixes +to the userbase. + +# Bug fixes + - [unsupported commands should not be available in safe interpreters](https://core.tcl-lang.org/tcl/tktview/82d12c) + - [Check for -municode doesn't work on WSL](https://core.tcl-lang.org/tcl/tktview/632710) + - [configure --enable-man-compression error](https://core.tcl-lang.org/tcl/tktview/886549) + - [nmake: rmdir and mkdir are picked from cygwin if available](https://core.tcl-lang.org/tcl/tktview/be40b7) + - [lseq: has incorrect results in edge cases](https://core.tcl-lang.org/tcl/tktview/999b69) + - [lseq: "count" error persists across calls](https://core.tcl-lang.org/tcl/tktview/8d1fc7) + - [lseq: Remove the ability to pass expressions as numeric values in the lseq command.](https://core.tcl-lang.org/tips/doc/trunk/tip/746.md) + - [Performance regression in expr in/ni operators](https://core.tcl-lang.org/tcl/info/8994c9) + - [Uninitialized memory access in setting script limits](https://core.tcl-lang.org/tcl/info/f7495f) + - [Crash when defining const if namespace does not exist](https://core.tcl-lang.org/tcl/info/4b22d8) + - [Glob errors with -directory option and patterns containing absolute paths (Windows)](https://core.tcl-lang.org/tcl/info/b0682c) + - [Glob errors with -directory option with trailing backslash (Windows)](https://core.tcl-lang.org/tcl/info/b0682c) + - [File normalization inconsistency for glob result (Windows)](https://core.tcl-lang.org/tcl/info/108904) + - [Avoid ClockClientData typedef redefinition](https://core.tcl-lang.org/tcl/info/4724f3) + - [Building sqlite3 for tcl8 redefines typedef](https://core.tcl-lang.org/tcl/info/ad08bc) + - [Inconsistent file join with volume-relative arguments](https://core.tcl-lang.org/tcl/info/1215dc) + - [mind PTHREAD_NULL as sentinel value vs legitimate pthread_t arg](https://core.tcl-lang.org/tcl/info/673f2d) + - [fileevent poor performance due to shimmering](https://core.tcl-lang.org/tcl/info/7da6c2) + +# Updated bundled packages, libraries, standards, data + - autoconf 2.73 + - http 2.10.2 + - Itcl 4.3.8 + - sqlite3 3.53.0 + - tcltest 2.5.11 + - Thread 3.0.6 + - tzdata 2026b + - zlib 1.3.2 + +Release Tcl 9.0.3 arises from the check-in with tag `core-9-0-3`. + +Tcl patch releases have the primary purpose of delivering bug fixes +to the userbase. + +# Bug fixes + - [On Unix, IsTimeNative() always defined but not always used](https://core.tcl-lang.org/tcl/tktview/6b8e39) + - [Tweak install permissions](https://core.tcl-lang.org/tcl/tktview/31d4fa) + - [interp creation resets encoding directory search path](https://core.tcl-lang.org/tcl/tktview/87b697) + - [Pointer arithmetic with NULL in buildInfoObjCmd()](https://core.tcl-lang.org/tcl/tktview/85fc8b) + - [TclPushVarName(): pointer overflow](https://core.tcl-lang.org/tcl/tktview/77059c) + - [Add IWYU export pragma annotations](https://core.tcl-lang.org/tcl/tktview/c7dc59) + - [Windows: Install man pages](https://core.tcl-lang.org/tcl/tktview/3161b7) + - [Windows: Install pkgconfig](https://core.tcl-lang.org/tcl/tktview/1cf49a) + - [Non-existent variables are ignored if re is {}](https://core.tcl-lang.org/tcl/tktview/cb03e5) + - [bug in single-argument 'max' with bignums](https://core.tcl-lang.org/tcl/tktview/8dd280) + - [Windows static builds: package require registry dde fails in child interpreters](https://core.tcl-lang.org/tcl/tktview/4f06d7) + - [Windows static builds: registry command is available in main interpreter without package require](https://core.tcl-lang.org/tcl/tktview/6094de) + +# Updated bundled packages, libraries, standards, data + - Itcl 4.3.5 + - http 2.10.1 + - opt 0.4.10 + - platform 1.1.0 + - sqlite3 3.51.0 + - tcltest 2.5.10 + - Thread 3.0.4 + - TDBC\* 1.1.13 + - dde 1.4.6 + - Unicode 17.0.0 + +Release Tcl 9.0.2 arises from the check-in with tag `core-9-0-2`. + +Tcl patch releases have the primary purpose of delivering bug fixes +to the userbase. + +# New commands and options + - [New command encoding user](https://core.tcl-lang.org/tips/doc/trunk/tip/716.md) + - [New exec option -encoding](https://core.tcl-lang.org/tips/doc/trunk/tip/716.md) + +# Bug fixes + - [Better error-message than "interpreter uses an incompatible stubs mechanism"](https://core.tcl-lang.org/tcl/tktview/fc3509) + - [\[$interp eval $lambda\] after \[eval $lambda\] or vice versa fails](https://core.tcl-lang.org/tcl/tktview/67d5f7) + - [tcl::mathfunc::isunordered inconsistency with some integer values](https://core.tcl-lang.org/tcl/tktview/98006f) + - [test lseq hangs with -Os](https://core.tcl-lang.org/tcl/tktview/d2a3c5) + - [exec does not handle app execution aliases on Windows](https://core.tcl-lang.org/tcl/tktview/4f0b57) + - [auto_execok does not find several built-in cmd commands](https://core.tcl-lang.org/tcl/tktview/4e2c8b) + - [Panic "Buffer Underflow, BUFFER_PADDING not enough"](https://core.tcl-lang.org/tcl/tktview/73bb42) + - [MS-VS build system: pckIndex.tcl when building for 9 misses "t" for TCL 8.6 part](https://core.tcl-lang.org/tcl/tktview/a77029) + - [clock format -locale does not look up locale children if parent locale used first](https://core.tcl-lang.org/tcl/tktview/2c0f49) + - [Missing libtcl?.?.dll.a in Cygwin](https://core.tcl-lang.org/tcl/tktview/dcedba) + - [tclEpollNotfy PlatformEventsControl panics if websocket disconnected](https://core.tcl-lang.org/tcl/tktview/010d8f) + - [Tcl_InitStubs compatibility for 9.1](https://core.tcl-lang.org/tcl/tktview/fd8341) + - [proc with more than 2**31 variables](https://core.tcl-lang.org/tcl/tktview/92aeb8) + - [scan "long mantissa" %g](https://core.tcl-lang.org/tcl/tktview/42d14c) + - ["encoding system": wrong result without manifest](https://core.tcl-lang.org/tcl/tktview/8ffd8c) + - [lseq crash on out-of-range index](https://core.tcl-lang.org/tcl/tktview/7d3101) + - [lseq crash on nested indices](https://core.tcl-lang.org/tcl/tktview/452b10) + - [Build broken (trunk branch) tclCompExpr.c tclOOCall.c](https://core.tcl-lang.org/tcl/tktview/1dcda0) + - [Memory allocation runaway on truncated iso2022 encoding](https://core.tcl-lang.org/tcl/tktview/7346ad) + - [Missing include dir for extensions in non-default locations](https://core.tcl-lang.org/tcl/tktview/333512) + - [tcl::tm::path doesn't handle tilde expand](https://core.tcl-lang.org/tcl/tktview/b87673) + - [lseq numeric overflow](https://core.tcl-lang.org/tcl/tktview/0ee626) + - ["return": broken ordering of nested -options](https://core.tcl-lang.org/tcl/tktview/ecf35c) + - [Euro/Tail-sign missing from cp864 encoding](https://core.tcl-lang.org/tcl/tktview/ecafd8) + - [use after free on TSD in Winsock](https://core.tcl-lang.org/tcl/tktview/40b181) + - [use after free on Windows pipe handles](https://core.tcl-lang.org/tcl/tktview/7c2716) + - [tcl::build-info not documented](https://core.tcl-lang.org/tcl/tktview/ef7042) + - [Fix 32 bit overflow in interp limit](https://core.tcl-lang.org/tcl/tktview/9dfae3) + +# Incompatibilities + - [The ActiveCodePage element has been removed from the Windows executable manifest for tclsh](https://core.tcl-lang.org/tips/doc/trunk/tip/716.md) + +# Updated bundled packages, libraries, standards, data + - Itcl 4.3.3 + - sqlite3 3.49.1 + - Thread 3.0.2 + - TDBC\* 1.1.11 + - tzdata 2025b + +Release Tcl 9.0.1 arises from the check-in with tag `core-9-0-1`. + +Tcl patch releases have the primary purpose of delivering bug fixes +to the userbase. As the first patch release in the Tcl 9.0.\* series, +Tcl 9.0.1 also includes a small number of interface changes that complete +some incomplete features first delivered in Tcl 9.0.0. + +# Completed 9.0 Features and Interfaces + - [TIP 701 - Tcl_FSTildeExpand C API](https://core.tcl-lang.org/tips/doc/trunk/tip/701.md) + - [TIP 707 - ptrAndSize internal rep in Tcl_Obj](https://core.tcl-lang.org/tips/doc/trunk/tip/707.md) + - [Size modifiers j, q, z, t not implemented]( https://core.tcl-lang.org/tcl/info/c4f365) + +# Bug fixes + - [regression in tzdata, %z instead of offset TZ-name](https://core.tcl-lang.org/tcl/tktview/2c237b) + - [Tcl will not start properly if there is an init.tcl file in the current dir](https://core.tcl-lang.org/tcl/tktview/43c94f) + - [clock scan "24:00", ISO-8601 compatibility](https://core.tcl-lang.org/tcl/tktview/aee9f2) + - [Temporary folder with file "tcl9registry13.dll" remains after "exit"](https://core.tcl-lang.org/tcl/tktview/6ce3c0) + - [Wrong result by "lsearch -stride -subindices -inline -all"](https://core.tcl-lang.org/tcl/info/5a1aaa) + - [TIP 609 - required Tcl_ThreadAlert() skipped with nested event loop](https://core.tcl-lang.org/tcl/info/c7e4c4) + - [buffer overwrite for non-BMP characters in utf-16](https://core.tcl-lang.org/tcl/tktview/66da4d) + - [zipfs info on mountpoint of executable returns zero offset in field 4"](https://core.tcl-lang.org/tcl/info/aaa84f) + - [zlib-8.8, zlib-8.16 fail on Fedora 40, gcc 14.1.1](https://core.tcl-lang.org/tcl/tktview/73d5cb) + - [install registry and dde in $INSTALL_DIR\lib always](https://core.tcl-lang.org/tcl/tktview/364bd9) + - [cannot build .chm help file (Windows)](https://core.tcl-lang.org/tcl/tktview/bb110c) + +# Incompatibilities + - No known incompatibilities with the Tcl 9.0.0 public interface. + +# Updated bundled packages, libraries, standards, data + - Itcl 4.3.2 + - sqlite3 3.47.2 + - Thread 3.0.1 + - TDBC\* 1.1.10 + - tcltest 2.5.9 + - tzdata 2024b, corrected + +Release Tcl 9.0.0 arises from the check-in with tag `core-9-0-0`. + +Highlighted differences between Tcl 9.0 and Tcl 8.6 are summarized below, +with focus on changes important to programmers using the Tcl library and +writing Tcl scripts. + +# Major Features + +## 64-bit capacity: Data values larger than 2Gb + - Strings can be any length (that fits in your available memory) + - Lists and dictionaries can have very large numbers of elements + +## Internationalization of text + - Full Unicode range of codepoints + - New encodings: `utf-16`/`utf-32`/`ucs-2`(`le`|`be`), `CESU-8`, etc. + - `encoding` options `-profile`, `-failindex` manage encoding of I/O. + - `msgcat` supports custom locale search list + - `source` defaults to `-encoding utf-8` + +## Zip filesystems and attached archives. + - Packaging of the Tcl script library with the Tcl binary library, + meaning that the `TCL_LIBRARY` environment variable is usually not required. + - Packaging of an application into a virtual filesystem is now a supported + core Tcl feature. + +## Unix notifiers available using `epoll()` or `kqueue()` + - This relieves limits on file descriptors imposed by legacy `select()` and fixes a performance bottleneck. + +# Incompatibilities + +## Notable incompatibilities + - Unqualified varnames resolved in current namespace, not global. + Note that in almost all cases where this causes a change, the change is actually the removal of a latent bug. + - No `--disable-threads` build option. Always thread-enabled. + - I/O malencoding default response: raise error (`-profile strict`) + - Windows platform needs Windows 7 or Windows Server 2008 R2 or later + - Ended interpretation of `~` as home directory in pathnames. + (See `file home` and `file tildeexpand` for replacements when you need them.) + - Removed the `identity` encoding. + (There were only ever very few valid use cases for this; almost all uses + were systematically wrong.) + - Removed the encoding alias `binary` to `iso8859-1`. + - `$::tcl_precision` no longer controls string generation of doubles. + (If you need a particular precision, use `format`.) + - Removed pre-Tcl 8 legacies: `case`, `puts` and `read` variant syntaxes. + - Removed subcommands [`trace variable`|`vdelete`|`vinfo`] + - Removed `-eofchar` option for write channels. + - On Windows 10+ (Version 1903 or higher), system encoding is always utf-8. + - `%b`/`%d`/`%o`/`%x` format modifiers (without size modifier) for `format` + and `scan` always truncate to 32-bits on all platforms. + - `%L` size modifier for `scan` no longer truncates to 64-bit. + - Removed command `::tcl::unsupported::inject`. + (See `coroinject` and `coroprobe` for supported commands with significantly + more comprehensible semantics.) + +## Incompatibilities in C public interface + - Extensions built against Tcl 8.6 and before will not work with Tcl 9.0; + ABI compatibility was a non-goal for 9.0. In _most_ cases, rebuilding + against Tcl 9.0 should work except when a removed API function is used. + - Many arguments expanded type from `int` to `Tcl_Size`, a signed integer type + large enough to support 64-bit sized memory objects. + The constant `TCL_AUTO_LENGTH` is a value of that type that indicates that + the length should be obtained using an appropriate function (typically `strlen()` for `char *` values). + - Ended support for `Tcl_ChannelTypeVersion` less than 5 + - Introduced versioning of the `Tcl_ObjType` struct + - Removed macros `CONST*`: Tcl 9 support means dropping Tcl 8.3 support. + (Replaced with standard C `const` keyword going forward.) + - Removed registration of several `Tcl_ObjType`s. + - Removed API functions: + + `Tcl_Backslash()`, + `Tcl_*VA()`, + `Tcl_*MathFunc*()`, + `Tcl_MakeSafe()`, + `Tcl_(Save|Restore|Discard|Free)Result()`, + `Tcl_EvalTokens()`, + `Tcl_(Get|Set)DefaultEncodingDir()`, + `Tcl_UniCharN(case)cmp()`, + `Tcl_UniCharCaseMatch()` + + - Revised many internals; beware reliance on undocumented behaviors. + +# New Features + +## New commands + - `array default` — Specify default values for arrays (note that this alters the behaviour of `append`, `incr`, `lappend`). + - `array for` — Cheap iteration over an array's contents. + - `chan isbinary` — Test if a channel is configured to work with binary data. + - `coroinject`, `coroprobe` — Interact with paused coroutines. + - `clock add weekdays` — Clock arithmetic with week days. + - `const`, `info const*` — Commands for defining constants (variables that can't be modified). + - `dict getwithdefault` — Define a fallback value to use when `dict get` would otherwise fail. + - `file home` — Get the user home directory. + - `file tempdir` — Create a temporary directory. + - `file tildeexpand` — Expand a file path containing a `~`. + - `info commandtype` — Introspection for the kinds of commands. + - `ledit` — Equivalent to `lreplace` but on a list in a variable. + - `lpop` — Remove an item from a list in a variable. + - `lremove` — Remove a sublist from a list in a variable. + - `lseq` — Generate a list of numbers in a sequence. + - `package files` — Describe the contents of a package. + - `string insert` — Insert a string as a substring of another string. + - `string is dict` — Test whether a string is a dictionary. + - `tcl::process` — Commands for working with subprocesses. + - `*::build-info` — Obtain information about the build of Tcl. + - `readFile`, `writeFile`, `foreachLine` — Simple procedures for basic working with files. + - `tcl::idna::*` — Commands for working with encoded DNS names. + +## New command options + - `chan configure ... -inputmode ...` — Support for raw terminal input and reading passwords. + - `clock scan ... -validate ...` + - `info loaded ... ?prefix?` + - `lsearch ... -stride ...` — Search a list by groups of items. + - `regsub ... -command ...` — Generate the replacement for a regular expression by calling a command. + - `socket ... -nodelay ... -keepalive ...` + - `vwait` controlled by several new options + - `expr` string comparators `lt`, `gt`, `le`, `ge` + - `expr` supports comments inside expressions + +## Numbers + - 0NNN format is no longer octal interpretation. Use 0oNNN. + - 0dNNNN format to compel decimal interpretation. + - NN_NNN_NNN, underscores in numbers for optional readability + - Functions: `isinf()`, `isnan()`, `isnormal()`, `issubnormal()`, `isunordered()` + - Command: `fpclassify` + - Function `int()` no longer truncates to word size + +## TclOO facilities + - private variables and methods + - class variables and methods + - abstract and singleton classes + - configurable properties + - `method -export`, `method -unexport` diff --git a/vendor/tcl/compat/README b/vendor/tcl/compat/README new file mode 100644 index 00000000..9af4285a --- /dev/null +++ b/vendor/tcl/compat/README @@ -0,0 +1,6 @@ +This directory contains various header and code files that are +used make Tcl compatible with various releases of UNIX and UNIX-like +systems. Typically, files from this directory are used to compile +Tcl when a system doesn't contain the corresponding files or when +they are known to be incorrect. When the whole world becomes POSIX- +compliant this directory should be unnecessary. diff --git a/vendor/tcl/compat/dlfcn.h b/vendor/tcl/compat/dlfcn.h new file mode 100644 index 00000000..fb27ea0e --- /dev/null +++ b/vendor/tcl/compat/dlfcn.h @@ -0,0 +1,58 @@ +/* + * dlfcn.h -- + * + * This file provides a replacement for the header file "dlfcn.h" + * on systems where dlfcn.h is missing. It's primary use is for + * AIX, where Tcl emulates the dl library. + * + * This file is subject to the following copyright notice, which is + * different from the notice used elsewhere in Tcl but rougly + * equivalent in meaning. + * + * Copyright (c) 1992,1993,1995,1996, Jens-Uwe Mager, Helios Software GmbH + * Not derived from licensed software. + * + * Permission is granted to freely use, copy, modify, and redistribute + * this software, provided that the author is not construed to be liable + * for any results of using the software, alterations are clearly marked + * as such, and this notice is not modified. + */ + +/* + * This is an unpublished work copyright (c) 1992 HELIOS Software GmbH + * 30159 Hannover, Germany + */ + +#ifndef __dlfcn_h__ +#define __dlfcn_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Mode flags for the dlopen routine. + */ +#define RTLD_LAZY 1 /* lazy function call binding */ +#define RTLD_NOW 2 /* immediate function call binding */ +#define RTLD_GLOBAL 0x100 /* allow symbols to be global */ + +/* + * To be able to intialize, a library may provide a dl_info structure + * that contains functions to be called to initialize and terminate. + */ +struct dl_info { + void (*init) (void); + void (*fini) (void); +}; + +void *dlopen (const char *path, int mode); +void *dlsym (void *handle, const char *symbol); +char *dlerror (void); +int dlclose (void *handle); + +#ifdef __cplusplus +} +#endif + +#endif /* __dlfcn_h__ */ diff --git a/vendor/tcl/compat/fake-rfc2553.c b/vendor/tcl/compat/fake-rfc2553.c new file mode 100644 index 00000000..066f83f9 --- /dev/null +++ b/vendor/tcl/compat/fake-rfc2553.c @@ -0,0 +1,267 @@ +/* + * Copyright (C) 2000-2003 Damien Miller. All rights reserved. + * Copyright (C) 1999 WIDE Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Pseudo-implementation of RFC2553 name / address resolution functions + * + * But these functions are not implemented correctly. The minimum subset + * is implemented for ssh use only. For example, this routine assumes + * that ai_family is AF_INET. Don't use it for another purpose. + */ +#include "tclInt.h" + +TCL_DECLARE_MUTEX(netdbMutex) + +#ifndef HAVE_GETNAMEINFO +#ifndef HAVE_STRLCPY +static size_t +strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) { + do { + if ((*d++ = *s++) == 0) + break; + } while (--n != 0); + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} +#endif + +int fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host, + size_t hostlen, char *serv, size_t servlen, int flags) +{ + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + struct hostent *hp; + char tmpserv[16]; + (void)salen; + + if (sa->sa_family != AF_UNSPEC && sa->sa_family != AF_INET) + return (EAI_FAMILY); + if (serv != NULL) { + snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port)); + if (strlcpy(serv, tmpserv, servlen) >= servlen) + return (EAI_MEMORY); + } + + if (host != NULL) { + if (flags & NI_NUMERICHOST) { + size_t len; + Tcl_MutexLock(&netdbMutex); + len = strlcpy(host, inet_ntoa(sin->sin_addr), hostlen); + Tcl_MutexUnlock(&netdbMutex); + if (len >= hostlen) { + return (EAI_MEMORY); + } else { + return (0); + } + } else { + int ret; + Tcl_MutexLock(&netdbMutex); + hp = gethostbyaddr((char *)&sin->sin_addr, + sizeof(struct in_addr), AF_INET); + if (hp == NULL) { + ret = EAI_NODATA; + } else if (strlcpy(host, hp->h_name, hostlen) + >= hostlen) { + ret = EAI_MEMORY; + } else { + ret = 0; + } + Tcl_MutexUnlock(&netdbMutex); + return ret; + } + } + return (0); +} +#endif /* !HAVE_GETNAMEINFO */ + +#ifndef HAVE_GAI_STRERROR +const char * +fake_gai_strerror(int err) +{ + switch (err) { + case EAI_NODATA: + return ("no address associated with name"); + case EAI_MEMORY: + return ("memory allocation failure."); + case EAI_NONAME: + return ("nodename nor servname provided, or not known"); + case EAI_FAMILY: + return ("ai_family not supported"); + default: + return ("unknown/invalid error."); + } +} +#endif /* !HAVE_GAI_STRERROR */ + +#ifndef HAVE_FREEADDRINFO +void +fake_freeaddrinfo(struct addrinfo *ai) +{ + struct addrinfo *next; + + for(; ai != NULL;) { + next = ai->ai_next; + free(ai); + ai = next; + } +} +#endif /* !HAVE_FREEADDRINFO */ + +#ifndef HAVE_GETADDRINFO +static struct +addrinfo *malloc_ai(int port, u_long addr, const struct addrinfo *hints) +{ + struct addrinfo *ai; + + ai = (struct addrinfo *)malloc(sizeof(*ai) + sizeof(struct sockaddr_in)); + if (ai == NULL) + return (NULL); + + memset(ai, '\0', sizeof(*ai) + sizeof(struct sockaddr_in)); + + ai->ai_addr = (struct sockaddr *)(ai + 1); + /* XXX -- ssh doesn't use sa_len */ + ai->ai_addrlen = sizeof(struct sockaddr_in); + ai->ai_addr->sa_family = ai->ai_family = AF_INET; + + ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port; + ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr; + + /* XXX: the following is not generally correct, but does what we want */ + if (hints->ai_socktype) + ai->ai_socktype = hints->ai_socktype; + else + ai->ai_socktype = SOCK_STREAM; + + if (hints->ai_protocol) + ai->ai_protocol = hints->ai_protocol; + + return (ai); +} + +int +fake_getaddrinfo(const char *hostname, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) +{ + struct hostent *hp; + struct servent *sp; + struct in_addr in; + int i; + long int port; + u_long addr; + + port = 0; + if (hints && hints->ai_family != AF_UNSPEC && + hints->ai_family != AF_INET) + return (EAI_FAMILY); + if (servname != NULL) { + char *cp; + + port = strtol(servname, &cp, 10); + if (port > 0 && port <= 65535 && *cp == '\0') + port = htons((unsigned short)port); + else if ((sp = getservbyname(servname, NULL)) != NULL) + port = sp->s_port; + else + port = 0; + } + + if (hints && hints->ai_flags & AI_PASSIVE) { + addr = htonl(0x00000000); + if (hostname && inet_aton(hostname, &in) != 0) + addr = in.s_addr; + *res = malloc_ai(port, addr, hints); + if (*res == NULL) + return (EAI_MEMORY); + return (0); + } + + if (!hostname) { + *res = malloc_ai(port, htonl(0x7F000001), hints); + if (*res == NULL) + return (EAI_MEMORY); + return (0); + } + + if (inet_aton(hostname, &in)) { + *res = malloc_ai(port, in.s_addr, hints); + if (*res == NULL) + return (EAI_MEMORY); + return (0); + } + + /* Don't try DNS if AI_NUMERICHOST is set */ + if (hints && hints->ai_flags & AI_NUMERICHOST) + return (EAI_NONAME); + + Tcl_MutexLock(&netdbMutex); + hp = gethostbyname(hostname); + if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) { + struct addrinfo *cur, *prev; + + cur = prev = *res = NULL; + for (i = 0; hp->h_addr_list[i]; i++) { + struct in_addr *in = (struct in_addr *)hp->h_addr_list[i]; + + cur = malloc_ai(port, in->s_addr, hints); + if (cur == NULL) { + if (*res != NULL) + freeaddrinfo(*res); + Tcl_MutexUnlock(&netdbMutex); + return (EAI_MEMORY); + } + if (prev) + prev->ai_next = cur; + else + *res = cur; + + prev = cur; + } + Tcl_MutexUnlock(&netdbMutex); + return (0); + } + Tcl_MutexUnlock(&netdbMutex); + return (EAI_NODATA); +} +#endif /* !HAVE_GETADDRINFO */ diff --git a/vendor/tcl/compat/fake-rfc2553.h b/vendor/tcl/compat/fake-rfc2553.h new file mode 100644 index 00000000..64131702 --- /dev/null +++ b/vendor/tcl/compat/fake-rfc2553.h @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2000-2003 Damien Miller. All rights reserved. + * Copyright (C) 1999 WIDE Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Pseudo-implementation of RFC2553 name / address resolution functions + * + * But these functions are not implemented correctly. The minimum subset + * is implemented for ssh use only. For example, this routine assumes + * that ai_family is AF_INET. Don't use it for another purpose. + */ + +#ifndef _FAKE_RFC2553_H +#define _FAKE_RFC2553_H + +/* + * First, socket and INET6 related definitions + */ +#ifndef HAVE_STRUCT_SOCKADDR_STORAGE +# define _SS_MAXSIZE 128 /* Implementation specific max size */ +# define _SS_PADSIZE (_SS_MAXSIZE - sizeof (struct sockaddr)) +struct sockaddr_storage { + struct sockaddr ss_sa; + char __ss_pad2[_SS_PADSIZE]; +}; +# define ss_family ss_sa.sa_family +#endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */ + +#ifndef IN6_IS_ADDR_LOOPBACK +# define IN6_IS_ADDR_LOOPBACK(a) \ + (((uint32_t *)(a))[0] == 0 && ((uint32_t *)(a))[1] == 0 && \ + ((uint32_t *)(a))[2] == 0 && ((uint32_t *)(a))[3] == htonl(1)) +#endif /* !IN6_IS_ADDR_LOOPBACK */ + +#ifndef HAVE_STRUCT_IN6_ADDR +struct in6_addr { + uint8_t s6_addr[16]; +}; +#endif /* !HAVE_STRUCT_IN6_ADDR */ + +#ifndef HAVE_STRUCT_SOCKADDR_IN6 +struct sockaddr_in6 { + unsigned short sin6_family; + uint16_t sin6_port; + uint32_t sin6_flowinfo; + struct in6_addr sin6_addr; + uint32_t sin6_scope_id; +}; +#endif /* !HAVE_STRUCT_SOCKADDR_IN6 */ + +#ifndef AF_INET6 +/* Define it to something that should never appear */ +#define AF_INET6 AF_MAX +#endif + +/* + * Next, RFC2553 name / address resolution API + */ + +#ifndef NI_NUMERICHOST +# define NI_NUMERICHOST (1) +#endif +#ifndef NI_NAMEREQD +# define NI_NAMEREQD (1<<1) +#endif +#ifndef NI_NUMERICSERV +# define NI_NUMERICSERV (1<<2) +#endif + +#ifndef AI_PASSIVE +# define AI_PASSIVE (1) +#endif +#ifndef AI_CANONNAME +# define AI_CANONNAME (1<<1) +#endif +#ifndef AI_NUMERICHOST +# define AI_NUMERICHOST (1<<2) +#endif + +#ifndef NI_MAXSERV +# define NI_MAXSERV 32 +#endif /* !NI_MAXSERV */ +#ifndef NI_MAXHOST +# define NI_MAXHOST 1025 +#endif /* !NI_MAXHOST */ + +#ifndef EAI_NODATA +# define EAI_NODATA (INT_MAX - 1) +#endif +#ifndef EAI_MEMORY +# define EAI_MEMORY (INT_MAX - 2) +#endif +#ifndef EAI_NONAME +# define EAI_NONAME (INT_MAX - 3) +#endif +#ifndef EAI_SYSTEM +# define EAI_SYSTEM (INT_MAX - 4) +#endif +#ifndef EAI_FAMILY +# define EAI_FAMILY (INT_MAX - 5) +#endif +#ifndef EAI_SERVICE +# define EAI_SERVICE -8 /* SERVICE not supported for `ai_socktype'. */ +#endif + +#ifndef HAVE_STRUCT_ADDRINFO +struct addrinfo { + int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* length of ai_addr */ + char *ai_canonname; /* canonical name for hostname */ + struct sockaddr *ai_addr; /* binary address */ + struct addrinfo *ai_next; /* next structure in linked list */ +}; +#endif /* !HAVE_STRUCT_ADDRINFO */ + +#ifndef HAVE_GETADDRINFO +#ifdef getaddrinfo +# undef getaddrinfo +#endif +#define getaddrinfo(a,b,c,d) (fake_getaddrinfo(a,b,c,d)) +int getaddrinfo(const char *, const char *, + const struct addrinfo *, struct addrinfo **); +#endif /* !HAVE_GETADDRINFO */ + +#ifndef HAVE_GAI_STRERROR +#define gai_strerror(a) (fake_gai_strerror(a)) +const char *gai_strerror(int); +#endif /* !HAVE_GAI_STRERROR */ + +#ifndef HAVE_FREEADDRINFO +#define freeaddrinfo(a) (fake_freeaddrinfo(a)) +void freeaddrinfo(struct addrinfo *); +#endif /* !HAVE_FREEADDRINFO */ + +#ifndef HAVE_GETNAMEINFO +#define getnameinfo(a,b,c,d,e,f,g) (fake_getnameinfo(a,b,c,d,e,f,g)) +int getnameinfo(const struct sockaddr *, size_t, char *, size_t, + char *, size_t, int); +#endif /* !HAVE_GETNAMEINFO */ + + +#endif /* !_FAKE_RFC2553_H */ diff --git a/vendor/tcl/compat/gettod.c b/vendor/tcl/compat/gettod.c new file mode 100644 index 00000000..f6651d4a --- /dev/null +++ b/vendor/tcl/compat/gettod.c @@ -0,0 +1,31 @@ +/* + * gettod.c -- + * + * This file provides the gettimeofday function on systems + * that only have the System V ftime function. + * + * Copyright (c) 1995 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#include "tclPort.h" +#include + +#undef timezone + +int +gettimeofday( + struct timeval *tp, + struct timezone *tz) +{ + struct timeb t; + (void)tz; + + ftime(&t); + tp->tv_sec = t.time; + tp->tv_usec = t.millitm * 1000; + return 0; +} + diff --git a/vendor/tcl/compat/license.terms b/vendor/tcl/compat/license.terms new file mode 100644 index 00000000..d8049cd9 --- /dev/null +++ b/vendor/tcl/compat/license.terms @@ -0,0 +1,40 @@ +This software is copyrighted by the Regents of the University of +California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState +Corporation and other parties. The following terms apply to all files +associated with the software unless explicitly disclaimed in +individual files. + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, provided +that existing copyright notices are retained in all copies and that this +notice is included verbatim in any distributions. No written agreement, +license, or royalty fee is required for any of the authorized uses. +Modifications to this software may be copyrighted by their authors +and need not follow the licensing terms described here, provided that +the new terms are clearly indicated on the first page of each file where +they apply. + +IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY +FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY +DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE +IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE +NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR +MODIFICATIONS. + +GOVERNMENT USE: If you are acquiring this software on behalf of the +U.S. government, the Government shall have only "Restricted Rights" +in the software and related documentation as defined in the Federal +Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you +are acquiring the software on behalf of the Department of Defense, the +software shall be classified as "Commercial Computer Software" and the +Government shall have only "Restricted Rights" as defined in Clause +252.227-7014 (b) (3) of DFARs. Notwithstanding the foregoing, the +authors grant the U.S. Government and others acting in its behalf +permission to use and distribute the software in accordance with the +terms specified in this license. diff --git a/vendor/tcl/compat/mkstemp.c b/vendor/tcl/compat/mkstemp.c new file mode 100644 index 00000000..feccfbb2 --- /dev/null +++ b/vendor/tcl/compat/mkstemp.c @@ -0,0 +1,79 @@ +/* + * mkstemp.c -- + * + * Source code for the "mkstemp" library routine. + * + * Copyright (c) 2009 Donal K. Fellows + * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#include +#include +#include +#include +#include + +/* + *---------------------------------------------------------------------- + * + * mkstemp -- + * + * Create an open temporary file from a template. + * + * Results: + * A file descriptor, or -1 (with errno set) in the case of an error. + * + * Side effects: + * The template is updated to contain the real filename. + * + *---------------------------------------------------------------------- + */ + +int +mkstemp( + char *tmpl) /* Template for filename. */ +{ + static const char alphanumerics[] = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + char *a, *b; + int fd, count, alphanumericsLen = strlen(alphanumerics); /* == 62 */ + + a = tmpl + strlen(tmpl); + while (a > tmpl && *(a-1) == 'X') { + a--; + } + + if (a == tmpl) { + errno = ENOENT; + return -1; + } + + /* + * We'll only try up to 10 times; after that, we're suffering from enemy + * action and should let the caller know. + */ + + count = 10; + do { + /* + * Replace the X's in the original template with random alphanumeric + * digits. + */ + + for (b=a ; *b ; b++) { + float r = rand() / ((float) RAND_MAX); + + *b = alphanumerics[(int)(r * alphanumericsLen)]; + } + + /* + * Template is now realized; try to open (with correct options). + */ + + fd = open(tmpl, O_RDWR|O_CREAT|O_EXCL, 0600); + } while (fd == -1 && errno == EEXIST && --count > 0); + + return fd; +} diff --git a/vendor/tcl/compat/strncasecmp.c b/vendor/tcl/compat/strncasecmp.c new file mode 100644 index 00000000..0a69f353 --- /dev/null +++ b/vendor/tcl/compat/strncasecmp.c @@ -0,0 +1,136 @@ +/* + * strncasecmp.c -- + * + * Source code for the "strncasecmp" library routine. + * + * Copyright (c) 1988-1993 The Regents of the University of California. + * Copyright (c) 1995-1996 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#include "tclPort.h" + +/* + * This array is designed for mapping upper and lower case letter together for + * a case independent comparison. The mappings are based upon ASCII character + * sequences. + */ + +static const unsigned char charmap[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xe1, 0xe2, 0xe3, 0xe4, 0xc5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, +}; + +/* + * Here are the prototypes just in case they are not included in tclPort.h. + */ + +int strncasecmp(const char *s1, const char *s2, size_t n); +int strcasecmp(const char *s1, const char *s2); + +/* + *---------------------------------------------------------------------- + * + * strcasecmp -- + * + * Compares two strings, ignoring case differences. + * + * Results: + * Compares two null-terminated strings s1 and s2, returning -1, 0, or 1 + * if s1 is lexicographically less than, equal to, or greater than s2. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +strcasecmp( + const char *s1, /* First string. */ + const char *s2) /* Second string. */ +{ + unsigned char u1, u2; + + for ( ; ; s1++, s2++) { + u1 = (unsigned char) *s1; + u2 = (unsigned char) *s2; + if ((u1 == '\0') || (charmap[u1] != charmap[u2])) { + break; + } + } + return charmap[u1] - charmap[u2]; +} + +/* + *---------------------------------------------------------------------- + * + * strncasecmp -- + * + * Compares two strings, ignoring case differences. + * + * Results: + * Compares up to length chars of s1 and s2, returning -1, 0, or 1 if s1 + * is lexicographically less than, equal to, or greater than s2 over + * those characters. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +strncasecmp( + const char *s1, /* First string. */ + const char *s2, /* Second string. */ + size_t length) /* Maximum number of characters to compare + * (stop earlier if the end of either string + * is reached). */ +{ + unsigned char u1, u2; + + for (; length != 0; length--, s1++, s2++) { + u1 = (unsigned char) *s1; + u2 = (unsigned char) *s2; + if (charmap[u1] != charmap[u2]) { + return charmap[u1] - charmap[u2]; + } + if (u1 == '\0') { + return 0; + } + } + return 0; +} diff --git a/vendor/tcl/compat/waitpid.c b/vendor/tcl/compat/waitpid.c new file mode 100644 index 00000000..cd04d8bb --- /dev/null +++ b/vendor/tcl/compat/waitpid.c @@ -0,0 +1,172 @@ +/* + * waitpid.c -- + * + * This procedure emulates the POSIX waitpid kernel call on BSD systems + * that don't have waitpid but do have wait3. This code is based on a + * prototype version written by Mark Diekhans and Karl Lehenbauer. + * + * Copyright (c) 1993 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#include "tclPort.h" + +#ifndef pid_t +#define pid_t int +#endif + +/* + * A linked list of the following structures is used to keep track of + * processes for which we received notification from the kernel, but the + * application hasn't waited for them yet (this can happen because wait may + * not return the process we really want). We save the information here until + * the application finally does wait for the process. + */ + +typedef struct WaitInfo { + pid_t pid; /* Pid of process that exited. */ + WAIT_STATUS_TYPE status; /* Status returned when child exited or + * suspended. */ + struct WaitInfo *nextPtr; /* Next in list of exited processes. */ +} WaitInfo; + +static WaitInfo *deadList = NULL; + /* First in list of all dead processes. */ + +/* + *---------------------------------------------------------------------- + * + * waitpid -- + * + * This procedure emulates the functionality of the POSIX waitpid kernel + * call, using the BSD wait3 kernel call. Note: it doesn't emulate + * absolutely all of the waitpid functionality, in that it doesn't + * support pid's of 0 or < -1. + * + * Results: + * -1 is returned if there is an error in the wait kernel call. Otherwise + * the pid of an exited or suspended process is returned and *statusPtr + * is set to the status value of the process. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +#ifdef waitpid +# undef waitpid +#endif + +pid_t +waitpid( + pid_t pid, /* The pid to wait on. Must be -1 or greater + * than zero. */ + int *statusPtr, /* Where to store wait status for the + * process. */ + int options) /* OR'ed combination of WNOHANG and + * WUNTRACED. */ +{ + WaitInfo *waitPtr, *prevPtr; + pid_t result; + WAIT_STATUS_TYPE status; + + if ((pid < -1) || (pid == 0)) { + errno = EINVAL; + return -1; + } + + /* + * See if there's a suitable process that has already stopped or exited. + * If so, remove it from the list of exited processes and return its + * information. + */ + + for (waitPtr = deadList, prevPtr = NULL; waitPtr != NULL; + prevPtr = waitPtr, waitPtr = waitPtr->nextPtr) { + if ((pid != waitPtr->pid) && (pid != -1)) { + continue; + } + if (!(options & WUNTRACED) && (WIFSTOPPED(waitPtr->status))) { + continue; + } + result = waitPtr->pid; + *statusPtr = *((int *) &waitPtr->status); + if (prevPtr == NULL) { + deadList = waitPtr->nextPtr; + } else { + prevPtr->nextPtr = waitPtr->nextPtr; + } + Tcl_Free(waitPtr); + return result; + } + + /* + * Wait for any process to stop or exit. If it's an acceptable one then + * return it to the caller; otherwise store information about it in the + * list of exited processes and try again. On systems that have only wait + * but not wait3, there are several situations we can't handle, but we do + * the best we can (e.g. can still handle some combinations of options by + * invoking wait instead of wait3). + */ + + while (1) { +#if NO_WAIT3 + if (options & WNOHANG) { + return 0; + } + if (options != 0) { + errno = EINVAL; + return -1; + } + result = wait(&status); +#else + result = wait3(&status, options, 0); +#endif + if ((result == -1) && (errno == EINTR)) { + continue; + } + if (result <= 0) { + return result; + } + + if ((pid != result) && (pid != -1)) { + goto saveInfo; + } + if (!(options & WUNTRACED) && (WIFSTOPPED(status))) { + goto saveInfo; + } + *statusPtr = *((int *) &status); + return result; + + /* + * Can't return this info to caller. Save it in the list of stopped or + * exited processes. Tricky point: first check for an existing entry + * for the process and overwrite it if it exists (e.g. a previously + * stopped process might now be dead). + */ + + saveInfo: + for (waitPtr = deadList; waitPtr != NULL; waitPtr = waitPtr->nextPtr) { + if (waitPtr->pid == result) { + waitPtr->status = status; + goto waitAgain; + } + } + waitPtr = (WaitInfo *) Tcl_AttemptAlloc(sizeof(WaitInfo)); + if (!waitPtr) { + errno = ENOMEM; + return -1; + } + waitPtr->pid = result; + waitPtr->status = status; + waitPtr->nextPtr = deadList; + deadList = waitPtr; + + waitAgain: + continue; + } +} diff --git a/vendor/tcl/compat/zlib/BUILD.bazel b/vendor/tcl/compat/zlib/BUILD.bazel new file mode 100644 index 00000000..9a294f2f --- /dev/null +++ b/vendor/tcl/compat/zlib/BUILD.bazel @@ -0,0 +1,134 @@ +# Copied from https://github.com/bazelbuild/bazel-central-registry/tree/main/modules/zlib/1.3.1.bcr.4/patches +# Adapted from https://github.com/protocolbuffers/protobuf/blob/master/third_party/zlib.BUILD + +# Copyright 2008 Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Code generated by the Protocol Buffer compiler is owned by the owner +# of the input file used when generating it. This code is not +# standalone and requires a support library to be linked with it. This +# support library is itself covered by the above license. + +load("@rules_cc//cc:defs.bzl", "cc_library") +load("@rules_license//rules:license.bzl", "license") + +package( + default_applicable_licenses = [":license"], +) + +license( + name = "license", + license_kinds = ["@rules_license//licenses/spdx:Zlib"], + license_text = "LICENSE", +) + +exports_files([ + "LICENSE", +]) + +_ZLIB_HEADERS = [ + "crc32.h", + "deflate.h", + "gzguts.h", + "inffast.h", + "inffixed.h", + "inflate.h", + "inftrees.h", + "trees.h", + "zconf.h", + "zlib.h", + "zutil.h", +] + +_ZLIB_PREFIXED_HEADERS = ["zlib/include/" + hdr for hdr in _ZLIB_HEADERS] + +# In order to limit the damage from the `includes` propagation +# via `:zlib`, copy the public headers to a subdirectory and +# expose those. +genrule( + name = "copy_public_headers", + srcs = _ZLIB_HEADERS, + outs = _ZLIB_PREFIXED_HEADERS, + cmd_bash = "cp $(SRCS) $(@D)/zlib/include/", + cmd_bat = " && ".join( + ["@copy /Y \"$(location %s)\" \"$(@D)\\zlib\\include\\\" >NUL" % + s for s in _ZLIB_HEADERS], + ), +) + +config_setting( + name = "mingw_gcc_compiler", + flag_values = { + "@bazel_tools//tools/cpp:compiler": "mingw-gcc", + }, + visibility = [":__subpackages__"], +) + +cc_library( + name = "z", + srcs = [ + "adler32.c", + "compress.c", + "crc32.c", + "deflate.c", + "gzclose.c", + "gzlib.c", + "gzread.c", + "gzwrite.c", + "infback.c", + "inffast.c", + "inflate.c", + "inftrees.c", + "trees.c", + "uncompr.c", + "zutil.c", + # Include the un-prefixed headers in srcs to work + # around the fact that zlib isn't consistent in its + # choice of <> or "" delimiter when including itself. + ] + _ZLIB_HEADERS, + hdrs = _ZLIB_PREFIXED_HEADERS, + copts = select({ + ":mingw_gcc_compiler": [ + "-fpermissive", + ], + "@platforms//os:windows": [], + "//conditions:default": [ + "-Wno-deprecated-non-prototype", + "-Wno-unused-variable", + "-Wno-implicit-function-declaration", + ], + }), + includes = ["zlib/include/"], + visibility = ["//visibility:public"], +) + +alias( + name = "zlib", + actual = ":z", + visibility = ["//visibility:public"], +) diff --git a/vendor/tcl/compat/zlib/CMakeLists.txt b/vendor/tcl/compat/zlib/CMakeLists.txt new file mode 100644 index 00000000..e103c409 --- /dev/null +++ b/vendor/tcl/compat/zlib/CMakeLists.txt @@ -0,0 +1,310 @@ +cmake_minimum_required(VERSION 3.12...3.31) + +project( + zlib + LANGUAGES C + VERSION 1.3.2 + HOMEPAGE_URL "https://zlib.net/" + DESCRIPTION "a general-purpose lossless data-compression library") + +# ============================================================================ +# CPack +# ============================================================================ +set(CPACK_PACKAGE_VENDOR "zlib-Project") +set(CPACK_PACKAGE_DESCRIPTION_FILE ${zlib_SOURCE_DIR}/README) +set(CPACK_RESOURCE_FILE_LICENSE ${zlib_SOURCE_DIR}/LICENSE) +set(CPACK_RESOURCE_FILE_README ${zlib_SOURCE_DIR}/README) + +# ============================================================================ +# configuration +# ============================================================================ + +option(ZLIB_BUILD_TESTING "Enable Zlib Examples as tests" ON) +option(ZLIB_BUILD_SHARED "Enable building zlib shared library" ON) +option(ZLIB_BUILD_STATIC "Enable building zlib static library" ON) +option(ZLIB_INSTALL "Enable installation of zlib" ON) +option(ZLIB_PREFIX "prefix for all types and library functions, see zconf.h.in" + OFF) +mark_as_advanced(ZLIB_PREFIX) + +get_property(IS_MULTI GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + +if(NOT DEFINED CMAKE_BUILD_TYPE AND NOT IS_MULTI) + message(STATUS "No CMAKE_BUILD_TYPE set -- using Release") + set(CMAKE_BUILD_TYPE Release) +endif(NOT DEFINED CMAKE_BUILD_TYPE AND NOT IS_MULTI) + +include(CheckCSourceCompiles) +include(CheckFunctionExists) +include(CheckIncludeFile) +include(CMakePackageConfigHelpers) +include(CheckTypeSize) +include(CPack) +include(GNUInstallDirs) + +set(CPACK_INCLUDED TRUE) + +if(NOT ZLIB_CONF_WRITTEN) + set(Z_PREFIX ${ZLIB_PREFIX}) + set(CONF_OUT_FILE ${zlib_BINARY_DIR}/zconf.h.cmakein) + file(READ ${zlib_SOURCE_DIR}/zconf.h ZCONF_CONTENT LIMIT 245) + file(WRITE ${CONF_OUT_FILE} ${ZCONF_CONTENT}) + file(APPEND ${CONF_OUT_FILE} "#cmakedefine Z_PREFIX 1\n") + file(APPEND ${CONF_OUT_FILE} "#cmakedefine HAVE_STDARG_H 1\n") + file(APPEND ${CONF_OUT_FILE} "#cmakedefine HAVE_UNISTD_H 1\n") + file(READ ${zlib_SOURCE_DIR}/zconf.h ZCONF_CONTENT OFFSET 244) + set(FIRST_ITEM TRUE) + + foreach(item IN LISTS ZCONF_CONTENT) + if(FIRST_ITEM) + string(APPEND OUT_CONTENT ${item}) + set(FIRST_ITEM FALSE) + else(FIRST_ITEM) + string(APPEND OUT_CONTENT "\;" ${item}) + endif(FIRST_ITEM) + endforeach(item IN LISTS ${ZCONF_CONTENT}) + + file(APPEND ${CONF_OUT_FILE} ${OUT_CONTENT}) + set(ZLIB_CONF_WRITTEN + TRUE + CACHE BOOL "zconf.h.cmakein was created") + mark_as_advanced(ZLIB_CONF_WRITTEN) +endif(NOT ZLIB_CONF_WRITTEN) + +# +# Check to see if we have large file support +# +set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1) +check_type_size(off64_t OFF64_T) +unset(CMAKE_REQUIRED_DEFINITIONS) # clear variable + +# +# Check for fseeko +# +check_function_exists(fseeko HAVE_FSEEKO) + +# +# Check for stdarg.h +# +check_include_file(stdarg.h HAVE_STDARG_H) + +# +# Check for unistd.h +# +check_include_file(unistd.h HAVE_UNISTD_H) + +# +# Check visibility attribute is supported +# +if(MSVC) + set(CMAKE_REQUIRED_FLAGS "-WX") +else(MSVC) + set(CMAKE_REQUIRED_FLAGS "-Werror") +endif(MSVC) + +check_c_source_compiles( + " + #include + static void f(void) __attribute__ ((visibility(\"hidden\"))); + int main(void) {return 0;} + " + HAVE___ATTR__VIS_HIDDEN) + +unset(CMAKE_COMPILE_FLAGS) +set(ZLIB_PC ${zlib_BINARY_DIR}/zlib.pc) +configure_file(${zlib_SOURCE_DIR}/zlib.pc.cmakein ${ZLIB_PC} @ONLY) +configure_file(${zlib_BINARY_DIR}/zconf.h.cmakein ${zlib_BINARY_DIR}/zconf.h) + +# ============================================================================ +# zlib +# ============================================================================ + +set(ZLIB_PUBLIC_HDRS ${zlib_BINARY_DIR}/zconf.h zlib.h) + +set(ZLIB_PRIVATE_HDRS + crc32.h + deflate.h + gzguts.h + inffast.h + inffixed.h + inflate.h + inftrees.h + trees.h + zutil.h) + +set(ZLIB_SRCS + adler32.c + compress.c + crc32.c + deflate.c + gzclose.c + gzlib.c + gzread.c + gzwrite.c + inflate.c + infback.c + inftrees.c + inffast.c + trees.c + uncompr.c + zutil.c) + +if(WIN32) + set(zlib_static_suffix "s") + set(CMAKE_DEBUG_POSTFIX "d") +endif(WIN32) + +if(ZLIB_BUILD_SHARED) + add_library( + zlib SHARED ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS} + $<$,$>:win32/zlib1.rc>) + add_library(ZLIB::ZLIB ALIAS zlib) + target_include_directories( + zlib + PUBLIC $ + $ + $) + target_compile_definitions( + zlib + PRIVATE ZLIB_BUILD + $<$:NO_FSEEKO> + $<$:HAVE_HIDDEN> + $<$:_CRT_SECURE_NO_DEPRECATE> + $<$:_CRT_NONSTDC_NO_DEPRECATE> + PUBLIC $<$:_LARGEFILE64_SOURCE=1>) + set(INSTALL_VERSION ${zlib_VERSION}) + + if(NOT CYGWIN) + set_target_properties(zlib PROPERTIES SOVERSION ${zlib_VERSION_MAJOR} + VERSION ${INSTALL_VERSION}) + endif(NOT CYGWIN) + + set_target_properties( + zlib + PROPERTIES DEFINE_SYMBOL ZLIB_DLL + EXPORT_NAME ZLIB + OUTPUT_NAME z) + if(UNIX + AND NOT APPLE + AND NOT (CMAKE_SYSTEM_NAME STREQUAL AIX) + AND NOT (CMAKE_SYSTEM_NAME STREQUAL SunOS)) + # On unix-like platforms the library is almost always called libz + set_target_properties( + zlib + PROPERTIES LINK_FLAGS + "-Wl,--version-script,\"${zlib_SOURCE_DIR}/zlib.map\"") + endif( + UNIX + AND NOT APPLE + AND NOT (CMAKE_SYSTEM_NAME STREQUAL AIX) + AND NOT (CMAKE_SYSTEM_NAME STREQUAL SunOS)) +endif(ZLIB_BUILD_SHARED) + +if(ZLIB_BUILD_STATIC) + add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} + ${ZLIB_PRIVATE_HDRS}) + add_library(ZLIB::ZLIBSTATIC ALIAS zlibstatic) + target_include_directories( + zlibstatic + PUBLIC $ + $ + $) + target_compile_definitions( + zlibstatic + PRIVATE ZLIB_BUILD + $<$:NO_FSEEKO> + $<$:HAVE_HIDDEN> + $<$:_CRT_SECURE_NO_DEPRECATE> + $<$:_CRT_NONSTDC_NO_DEPRECATE> + PUBLIC $<$:_LARGEFILE64_SOURCE=1>) + set_target_properties( + zlibstatic PROPERTIES EXPORT_NAME ZLIBSTATIC OUTPUT_NAME + z${zlib_static_suffix}) +endif(ZLIB_BUILD_STATIC) + +if(ZLIB_INSTALL) + if(ZLIB_BUILD_SHARED) + install( + TARGETS zlib + COMPONENT Runtime + EXPORT zlibSharedExport + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}") + install( + EXPORT zlibSharedExport + FILE ZLIB-shared.cmake + NAMESPACE ZLIB:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/zlib) + + if(MSVC) + install( + FILES $ + COMPONENT Runtime + DESTINATION ${CMAKE_INSTALL_BINDIR} + CONFIGURATIONS Debug OR RelWithDebInfo + OPTIONAL) + endif(MSVC) + endif(ZLIB_BUILD_SHARED) + + if(ZLIB_BUILD_STATIC) + install( + TARGETS zlibstatic + COMPONENT Development + EXPORT zlibStaticExport + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}") + install( + EXPORT zlibStaticExport + FILE ZLIB-static.cmake + NAMESPACE ZLIB:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/zlib) + endif(ZLIB_BUILD_STATIC) + + configure_package_config_file( + ${zlib_SOURCE_DIR}/zlibConfig.cmake.in + ${zlib_BINARY_DIR}/ZLIBConfig.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/zlib) + + write_basic_package_version_file( + "${zlib_BINARY_DIR}/ZLIBConfigVersion.cmake" + VERSION "${zlib_VERSION}" + COMPATIBILITY AnyNewerVersion) + + install(FILES ${zlib_BINARY_DIR}/ZLIBConfig.cmake + ${zlib_BINARY_DIR}/ZLIBConfigVersion.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/zlib) + install( + FILES ${ZLIB_PUBLIC_HDRS} + COMPONENT Development + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") + install( + FILES zlib.3 + COMPONENT Docs + DESTINATION "${CMAKE_INSTALL_MANDIR}/man3") + install( + FILES LICENSE + doc/algorithm.txt + doc/crc-doc.1.0.pdf + doc/rfc1950.txt + doc/rfc1951.txt + doc/rfc1952.txt + doc/txtvsbin.txt + COMPONENT Docs + DESTINATION "${CMAKE_INSTALL_DOCDIR}/zlib") + install( + FILES ${ZLIB_PC} + COMPONENT Development + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") +endif(ZLIB_INSTALL) + +# ============================================================================ +# Tests +# ============================================================================ +if(ZLIB_BUILD_TESTING) + enable_testing() + add_subdirectory(test) +endif(ZLIB_BUILD_TESTING) + +add_subdirectory(contrib) diff --git a/vendor/tcl/compat/zlib/ChangeLog b/vendor/tcl/compat/zlib/ChangeLog new file mode 100644 index 00000000..312753ed --- /dev/null +++ b/vendor/tcl/compat/zlib/ChangeLog @@ -0,0 +1,1669 @@ + + ChangeLog file for zlib + +Changes in 1.3.2 (17 Feb 2026) +- Continued rewrite of CMake build [Vollstrecker] +- Various portability improvements +- Various github workflow additions and improvements +- Check for negative lengths in crc32_combine functions +- Copy only the initialized window contents in inflateCopy +- Prevent the use of insecure functions without an explicit request +- Add compressBound_z and deflateBound_z functions for large values +- Use atomics to build inflate fixed tables once +- Add definition of ZLIB_INSECURE to build tests with c89 and c94 +- Add --undefined option to ./configure for UBSan checker +- Copy only the initialized deflate state in deflateCopy +- Zero inflate state on allocation +- Remove untgz from contrib +- Add _z versions of the compress and uncompress functions +- Vectorize the CRC-32 calculation on the s390x +- Set bit 11 of the zip header flags in minizip if UTF-8 +- Update OS/400 support +- Add a test to configure to check for a working compiler +- Check for invalid NULL pointer inputs to zlib operations +- Add --mandir to ./configure to specify manual directory +- Add LICENSE.Info-Zip to contrib/minizip +- Remove vstudio projects in lieu of cmake-generated projects +- Replace strcpy() with memcpy() in contrib/minizip + +Changes in 1.3.1.2 (8 Dec 2025) +- Improve portability to RISC OS +- Permit compiling contrib/minizip/unzip.c with decryption +- Enable build of shared library on AIX +- Make deflateBound() more conservative and handle Z_STREAM_END +- Add zipAlreadyThere() to minizip zip.c to help avoid duplicates +- Make z_off_t 64 bits by default +- Add deflateUsed() function to get the used bits in the last byte +- Avoid out-of-bounds pointer arithmetic in inflateCopy() +- Add Haiku to configure for proper LDSHARED settings +- Add Bazel targets +- Complete rewrite of CMake build [Vollstrecker] +- Clarify the use of errnum in gzerror() +- Note that gzseek() requests are deferred until the next operation +- Note the use of gzungetc() to run a deferred seek while reading +- Fix bug in inflatePrime() for 16-bit ints +- Add a "G" option to force gzip, disabling transparency in gzread() +- Improve the discrimination between trailing garbage and bad gzip +- Allow gzflush() to write empty gzip members +- Remove redundant frees of point list on error in examples/zran.c +- Clarify the use of inflateGetHeader() +- Update links to the RFCs +- Return all available uncompressed data on error in gzread.c +- Support non-blocking devices in the gz* routines +- Various other small improvements + +Changes in 1.3.1 (22 Jan 2024) +- Reject overflows of zip header fields in minizip +- Fix bug in inflateSync() for data held in bit buffer +- Add LIT_MEM define to use more memory for a small deflate speedup +- Fix decision on the emission of Zip64 end records in minizip +- Add bounds checking to ERR_MSG() macro, used by zError() +- Neutralize zip file traversal attacks in miniunz +- Fix a bug in ZLIB_DEBUG compiles in check_match() +- Various portability and appearance improvements + +Changes in 1.3 (18 Aug 2023) +- Remove K&R function definitions and zlib2ansi +- Fix bug in deflateBound() for level 0 and memLevel 9 +- Fix bug when gzungetc() is used immediately after gzopen() +- Fix bug when using gzflush() with a very small buffer +- Fix crash when gzsetparams() attempted for transparent write +- Fix test/example.c to work with FORCE_STORED +- Rewrite of zran in examples (see zran.c version history) +- Fix minizip to allow it to open an empty zip file +- Fix reading disk number start on zip64 files in minizip +- Fix logic error in minizip argument processing +- Add minizip testing to Makefile +- Read multiple bytes instead of byte-by-byte in minizip unzip.c +- Add memory sanitizer to configure (--memory) +- Various portability improvements +- Various documentation improvements +- Various spelling and typo corrections + +Changes in 1.2.13 (13 Oct 2022) +- Fix configure issue that discarded provided CC definition +- Correct incorrect inputs provided to the CRC functions +- Repair prototypes and exporting of new CRC functions +- Fix inflateBack to detect invalid input with distances too far +- Have infback() deliver all of the available output up to any error +- Fix a bug when getting a gzip header extra field with inflate() +- Fix bug in block type selection when Z_FIXED used +- Tighten deflateBound bounds +- Remove deleted assembler code references +- Various portability and appearance improvements + +Changes in 1.2.12 (27 Mar 2022) +- Cygwin does not have _wopen(), so do not create gzopen_w() there +- Permit a deflateParams() parameter change as soon as possible +- Limit hash table inserts after switch from stored deflate +- Fix bug when window full in deflate_stored() +- Fix CLEAR_HASH macro to be usable as a single statement +- Avoid a conversion error in gzseek when off_t type too small +- Have Makefile return non-zero error code on test failure +- Avoid some conversion warnings in gzread.c and gzwrite.c +- Update use of errno for newer Windows CE versions +- Small speedup to inflate [psumbera] +- Return an error if the gzputs string length can't fit in an int +- Add address checking in clang to -w option of configure +- Don't compute check value for raw inflate if asked to validate +- Handle case where inflateSync used when header never processed +- Avoid the use of ptrdiff_t +- Avoid an undefined behavior of memcpy() in gzappend() +- Avoid undefined behaviors of memcpy() in gz*printf() +- Avoid an undefined behavior of memcpy() in _tr_stored_block() +- Make the names in functions declarations identical to definitions +- Remove old assembler code in which bugs have manifested +- Fix deflateEnd() to not report an error at start of raw deflate +- Add legal disclaimer to README +- Emphasize the need to continue decompressing gzip members +- Correct the initialization requirements for deflateInit2() +- Fix a bug that can crash deflate on some input when using Z_FIXED +- Assure that the number of bits for deflatePrime() is valid +- Use a structure to make globals in enough.c evident +- Use a macro for the printf format of big_t in enough.c +- Clean up code style in enough.c, update version +- Use inline function instead of macro for index in enough.c +- Clarify that prefix codes are counted in enough.c +- Show all the codes for the maximum tables size in enough.c +- Add gznorm.c example, which normalizes gzip files +- Fix the zran.c example to work on a multiple-member gzip file +- Add tables for crc32_combine(), to speed it up by a factor of 200 +- Add crc32_combine_gen() and crc32_combine_op() for fast combines +- Speed up software CRC-32 computation by a factor of 1.5 to 3 +- Use atomic test and set, if available, for dynamic CRC tables +- Don't bother computing check value after successful inflateSync() +- Correct comment in crc32.c +- Add use of the ARMv8 crc32 instructions when requested +- Use ARM crc32 instructions if the ARM architecture has them +- Explicitly note that the 32-bit check values are 32 bits +- Avoid adding empty gzip member after gzflush with Z_FINISH +- Fix memory leak on error in gzlog.c +- Fix error in comment on the polynomial representation of a byte +- Clarify gz* function interfaces, referring to parameter names +- Change macro name in inflate.c to avoid collision in VxWorks +- Correct typo in blast.c +- Improve portability of contrib/minizip +- Fix indentation in minizip's zip.c +- Replace black/white with allow/block. (theresa-m) +- minizip warning fix if MAXU32 already defined. (gvollant) +- Fix unztell64() in minizip to work past 4GB. (Daniël Hörchner) +- Clean up minizip to reduce warnings for testing +- Add fallthrough comments for gcc +- Eliminate use of ULL constants +- Separate out address sanitizing from warnings in configure +- Remove destructive aspects of make distclean +- Check for cc masquerading as gcc or clang in configure +- Fix crc32.c to compile local functions only if used + +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 +- Fix bug in gzwrite.c that produced corrupt gzip files +- Remove files to be installed before copying them in Makefile.in +- Add warnings when compiling with assembler code + +Changes in 1.2.9 (31 Dec 2016) +- Fix contrib/minizip to permit unzipping with desktop API [Zouzou] +- Improve contrib/blast to return unused bytes +- Assure that gzoffset() is correct when appending +- Improve compress() and uncompress() to support large lengths +- Fix bug in test/example.c where error code not saved +- Remedy Coverity warning [Randers-Pehrson] +- Improve speed of gzprintf() in transparent mode +- Fix inflateInit2() bug when windowBits is 16 or 32 +- Change DEBUG macro to ZLIB_DEBUG +- Avoid uninitialized access by gzclose_w() +- Allow building zlib outside of the source directory +- Fix bug that accepted invalid zlib header when windowBits is zero +- Fix gzseek() problem on MinGW due to buggy _lseeki64 there +- Loop on write() calls in gzwrite.c in case of non-blocking I/O +- Add --warn (-w) option to ./configure for more compiler warnings +- Reject a window size of 256 bytes if not using the zlib wrapper +- Fix bug when level 0 used with Z_HUFFMAN or Z_RLE +- Add --debug (-d) option to ./configure to define ZLIB_DEBUG +- Fix bugs in creating a very large gzip header +- Add uncompress2() function, which returns the input size used +- Assure that deflateParams() will not switch functions mid-block +- Dramatically speed up deflation for level 0 (storing) +- Add gzfread(), duplicating the interface of fread() +- Add gzfwrite(), duplicating the interface of fwrite() +- Add deflateGetDictionary() function +- Use snprintf() for later versions of Microsoft C +- Fix *Init macros to use z_ prefix when requested +- Replace as400 with os400 for OS/400 support [Monnerat] +- Add crc32_z() and adler32_z() functions with size_t lengths +- Update Visual Studio project files [AraHaan] + +Changes in 1.2.8 (28 Apr 2013) +- Update contrib/minizip/iowin32.c for Windows RT [Vollant] +- Do not force Z_CONST for C++ +- Clean up contrib/vstudio [Roß] +- Correct spelling error in zlib.h +- Fix mixed line endings in contrib/vstudio + +Changes in 1.2.7.3 (13 Apr 2013) +- Fix version numbers and DLL names in contrib/vstudio/*/zlib.rc + +Changes in 1.2.7.2 (13 Apr 2013) +- Change check for a four-byte type back to hexadecimal +- Fix typo in win32/Makefile.msc +- Add casts in gzwrite.c for pointer differences + +Changes in 1.2.7.1 (24 Mar 2013) +- Replace use of unsafe string functions with snprintf if available +- Avoid including stddef.h on Windows for Z_SOLO compile [Niessink] +- Fix gzgetc undefine when Z_PREFIX set [Turk] +- Eliminate use of mktemp in Makefile (not always available) +- Fix bug in 'F' mode for gzopen() +- Add inflateGetDictionary() function +- Correct comment in deflate.h +- Use _snprintf for snprintf in Microsoft C +- On Darwin, only use /usr/bin/libtool if libtool is not Apple +- Delete "--version" file if created by "ar --version" [Richard G.] +- Fix configure check for veracity of compiler error return codes +- Fix CMake compilation of static lib for MSVC2010 x64 +- Remove unused variable in infback9.c +- Fix argument checks in gzlog_compress() and gzlog_write() +- Clean up the usage of z_const and respect const usage within zlib +- Clean up examples/gzlog.[ch] comparisons of different types +- Avoid shift equal to bits in type (caused endless loop) +- Fix uninitialized value bug in gzputc() introduced by const patches +- Fix memory allocation error in examples/zran.c [Nor] +- Fix bug where gzopen(), gzclose() would write an empty file +- Fix bug in gzclose() when gzwrite() runs out of memory +- Check for input buffer malloc failure in examples/gzappend.c +- Add note to contrib/blast to use binary mode in stdio +- Fix comparisons of differently signed integers in contrib/blast +- Check for invalid code length codes in contrib/puff +- Fix serious but very rare decompression bug in inftrees.c +- Update inflateBack() comments, since inflate() can be faster +- Use underscored I/O function names for WINAPI_FAMILY +- Add _tr_flush_bits to the external symbols prefixed by --zprefix +- Add contrib/vstudio/vc10 pre-build step for static only +- Quote --version-script argument in CMakeLists.txt +- Don't specify --version-script on Apple platforms in CMakeLists.txt +- Fix casting error in contrib/testzlib/testzlib.c +- Fix types in contrib/minizip to match result of get_crc_table() +- Simplify contrib/vstudio/vc10 with 'd' suffix +- Add TOP support to win32/Makefile.msc +- Support i686 and amd64 assembler builds in CMakeLists.txt +- Fix typos in the use of _LARGEFILE64_SOURCE in zconf.h +- Add vc11 and vc12 build files to contrib/vstudio +- Add gzvprintf() as an undocumented function in zlib +- Fix configure for Sun shell +- Remove runtime check in configure for four-byte integer type +- Add casts and consts to ease user conversion to C++ +- Add man pages for minizip and miniunzip +- In Makefile uninstall, don't rm if preceding cd fails +- Do not return Z_BUF_ERROR if deflateParam() has nothing to write + +Changes in 1.2.7 (2 May 2012) +- Replace use of memmove() with a simple copy for portability +- Test for existence of strerror +- Restore gzgetc_ for backward compatibility with 1.2.6 +- Fix build with non-GNU make on Solaris +- Require gcc 4.0 or later on Mac OS X to use the hidden attribute +- Include unistd.h for Watcom C +- Use __WATCOMC__ instead of __WATCOM__ +- Do not use the visibility attribute if NO_VIZ defined +- Improve the detection of no hidden visibility attribute +- Avoid using __int64 for gcc or solo compilation +- Cast to char * in gzprintf to avoid warnings [Zinser] +- Fix make_vms.com for VAX [Zinser] +- Don't use library or built-in byte swaps +- Simplify test and use of gcc hidden attribute +- Fix bug in gzclose_w() when gzwrite() fails to allocate memory +- Add "x" (O_EXCL) and "e" (O_CLOEXEC) modes support to gzopen() +- Fix bug in test/minigzip.c for configure --solo +- Fix contrib/vstudio project link errors [Mohanathas] +- Add ability to choose the builder in make_vms.com [Schweda] +- Add DESTDIR support to mingw32 win32/Makefile.gcc +- Fix comments in win32/Makefile.gcc for proper usage +- Allow overriding the default install locations for cmake +- Generate and install the pkg-config file with cmake +- Build both a static and a shared version of zlib with cmake +- Include version symbols for cmake builds +- If using cmake with MSVC, add the source directory to the includes +- Remove unneeded EXTRA_CFLAGS from win32/Makefile.gcc [Truta] +- Move obsolete emx makefile to old [Truta] +- Allow the use of -Wundef when compiling or using zlib +- Avoid the use of the -u option with mktemp +- Improve inflate() documentation on the use of Z_FINISH +- Recognize clang as gcc +- Add gzopen_w() in Windows for wide character path names +- Rename zconf.h in CMakeLists.txt to move it out of the way +- Add source directory in CMakeLists.txt for building examples +- Look in build directory for zlib.pc in CMakeLists.txt +- Remove gzflags from zlibvc.def in vc9 and vc10 +- Fix contrib/minizip compilation in the MinGW environment +- Update ./configure for Solaris, support --64 [Mooney] +- Remove -R. from Solaris shared build (possible security issue) +- Avoid race condition for parallel make (-j) running example +- Fix type mismatch between get_crc_table() and crc_table +- Fix parsing of version with "-" in CMakeLists.txt [Snider, Ziegler] +- Fix the path to zlib.map in CMakeLists.txt +- Force the native libtool in Mac OS X to avoid GNU libtool [Beebe] +- Add instructions to win32/Makefile.gcc for shared install [Torri] + +Changes in 1.2.6.1 (12 Feb 2012) +- Avoid the use of the Objective-C reserved name "id" +- Include io.h in gzguts.h for Microsoft compilers +- Fix problem with ./configure --prefix and gzgetc macro +- Include gz_header definition when compiling zlib solo +- Put gzflags() functionality back in zutil.c +- Avoid library header include in crc32.c for Z_SOLO +- Use name in GCC_CLASSIC as C compiler for coverage testing, if set +- Minor cleanup in contrib/minizip/zip.c [Vollant] +- Update make_vms.com [Zinser] +- Remove unnecessary gzgetc_ function +- Use optimized byte swap operations for Microsoft and GNU [Snyder] +- Fix minor typo in zlib.h comments [Rzesniowiecki] + +Changes in 1.2.6 (29 Jan 2012) +- Update the Pascal interface in contrib/pascal +- Fix function numbers for gzgetc_ in zlibvc.def files +- Fix configure.ac for contrib/minizip [Schiffer] +- Fix large-entry detection in minizip on 64-bit systems [Schiffer] +- Have ./configure use the compiler return code for error indication +- Fix CMakeLists.txt for cross compilation [McClure] +- Fix contrib/minizip/zip.c for 64-bit architectures [Dalsnes] +- Fix compilation of contrib/minizip on FreeBSD [Marquez] +- Correct suggested usages in win32/Makefile.msc [Shachar, Horvath] +- Include io.h for Turbo C / Borland C on all platforms [Truta] +- Make version explicit in contrib/minizip/configure.ac [Bosmans] +- Avoid warning for no encryption in contrib/minizip/zip.c [Vollant] +- Minor cleanup up contrib/minizip/unzip.c [Vollant] +- Fix bug when compiling minizip with C++ [Vollant] +- Protect for long name and extra fields in contrib/minizip [Vollant] +- Avoid some warnings in contrib/minizip [Vollant] +- Add -I../.. -L../.. to CFLAGS for minizip and miniunzip +- Add missing libs to minizip linker command +- Add support for VPATH builds in contrib/minizip +- Add an --enable-demos option to contrib/minizip/configure +- Add the generation of configure.log by ./configure +- Exit when required parameters not provided to win32/Makefile.gcc +- Have gzputc return the character written instead of the argument +- Use the -m option on ldconfig for BSD systems [Tobias] +- Correct in zlib.map when deflateResetKeep was added + +Changes in 1.2.5.3 (15 Jan 2012) +- Restore gzgetc function for binary compatibility +- Do not use _lseeki64 under Borland C++ [Truta] +- Update win32/Makefile.msc to build test/*.c [Truta] +- Remove old/visualc6 given CMakefile and other alternatives +- Update AS400 build files and documentation [Monnerat] +- Update win32/Makefile.gcc to build test/*.c [Truta] +- Permit stronger flushes after Z_BLOCK flushes +- Avoid extraneous empty blocks when doing empty flushes +- Permit Z_NULL arguments to deflatePending +- Allow deflatePrime() to insert bits in the middle of a stream +- Remove second empty static block for Z_PARTIAL_FLUSH +- Write out all of the available bits when using Z_BLOCK +- Insert the first two strings in the hash table after a flush + +Changes in 1.2.5.2 (17 Dec 2011) +- fix ld error: unable to find version dependency 'ZLIB_1.2.5' +- use relative symlinks for shared libs +- Avoid searching past window for Z_RLE strategy +- Assure that high-water mark initialization is always applied in deflate +- Add assertions to fill_window() in deflate.c to match comments +- Update python link in README +- Correct spelling error in gzread.c +- Fix bug in gzgets() for a concatenated empty gzip stream +- Correct error in comment for gz_make() +- Change gzread() and related to ignore junk after gzip streams +- Allow gzread() and related to continue after gzclearerr() +- Allow gzrewind() and gzseek() after a premature end-of-file +- Simplify gzseek() now that raw after gzip is ignored +- Change gzgetc() to a macro for speed (~40% speedup in testing) +- Fix gzclose() to return the actual error last encountered +- Always add large file support for windows +- Include zconf.h for windows large file support +- Include zconf.h.cmakein for windows large file support +- Update zconf.h.cmakein on make distclean +- Merge vestigial vsnprintf determination from zutil.h to gzguts.h +- Clarify how gzopen() appends in zlib.h comments +- Correct documentation of gzdirect() since junk at end now ignored +- Add a transparent write mode to gzopen() when 'T' is in the mode +- Update python link in zlib man page +- Get inffixed.h and MAKEFIXED result to match +- Add a ./config --solo option to make zlib subset with no library use +- Add undocumented inflateResetKeep() function for CAB file decoding +- Add --cover option to ./configure for gcc coverage testing +- Add #define ZLIB_CONST option to use const in the z_stream interface +- Add comment to gzdopen() in zlib.h to use dup() when using fileno() +- Note behavior of uncompress() to provide as much data as it can +- Add files in contrib/minizip to aid in building libminizip +- Split off AR options in Makefile.in and configure +- Change ON macro to Z_ARG to avoid application conflicts +- Facilitate compilation with Borland C++ for pragmas and vsnprintf +- Include io.h for Turbo C / Borland C++ +- Move example.c and minigzip.c to test/ +- Simplify incomplete code table filling in inflate_table() +- Remove code from inflate.c and infback.c that is impossible to execute +- Test the inflate code with full coverage +- Allow deflateSetDictionary, inflateSetDictionary at any time (in raw) +- Add deflateResetKeep and fix inflateResetKeep to retain dictionary +- Fix gzwrite.c to accommodate reduced memory zlib compilation +- Have inflate() with Z_FINISH avoid the allocation of a window +- Do not set strm->adler when doing raw inflate +- Fix gzeof() to behave just like feof() when read is not past end of file +- Fix bug in gzread.c when end-of-file is reached +- Avoid use of Z_BUF_ERROR in gz* functions except for premature EOF +- Document gzread() capability to read concurrently written files +- Remove hard-coding of resource compiler in CMakeLists.txt [Blammo] + +Changes in 1.2.5.1 (10 Sep 2011) +- Update FAQ entry on shared builds (#13) +- Avoid symbolic argument to chmod in Makefile.in +- Fix bug and add consts in contrib/puff [Oberhumer] +- Update contrib/puff/zeros.raw test file to have all block types +- Add full coverage test for puff in contrib/puff/Makefile +- Fix static-only-build install in Makefile.in +- Fix bug in unzGetCurrentFileInfo() in contrib/minizip [Kuno] +- Add libz.a dependency to shared in Makefile.in for parallel builds +- Spell out "number" (instead of "nb") in zlib.h for total_in, total_out +- Replace $(...) with `...` in configure for non-bash sh [Bowler] +- Add darwin* to Darwin* and solaris* to SunOS\ 5* in configure [Groffen] +- Add solaris* to Linux* in configure to allow gcc use [Groffen] +- Add *bsd* to Linux* case in configure [Bar-Lev] +- Add inffast.obj to dependencies in win32/Makefile.msc +- Correct spelling error in deflate.h [Kohler] +- Change libzdll.a again to libz.dll.a (!) in win32/Makefile.gcc +- Add test to configure for GNU C looking for gcc in output of $cc -v +- Add zlib.pc generation to win32/Makefile.gcc [Weigelt] +- Fix bug in zlib.h for _FILE_OFFSET_BITS set and _LARGEFILE64_SOURCE not +- Add comment in zlib.h that adler32_combine with len2 < 0 makes no sense +- Make NO_DIVIDE option in adler32.c much faster (thanks to John Reiser) +- Make stronger test in zconf.h to include unistd.h for LFS +- Apply Darwin patches for 64-bit file offsets to contrib/minizip [Slack] +- Fix zlib.h LFS support when Z_PREFIX used +- Add updated as400 support (removed from old) [Monnerat] +- Avoid deflate sensitivity to volatile input data +- Avoid division in adler32_combine for NO_DIVIDE +- Clarify the use of Z_FINISH with deflateBound() amount of space +- Set binary for output file in puff.c +- Use u4 type for crc_table to avoid conversion warnings +- Apply casts in zlib.h to avoid conversion warnings +- Add OF to prototypes for adler32_combine_ and crc32_combine_ [Miller] +- Improve inflateSync() documentation to note indeterminacy +- Add deflatePending() function to return the amount of pending output +- Correct the spelling of "specification" in FAQ [Randers-Pehrson] +- Add a check in configure for stdarg.h, use for gzprintf() +- Check that pointers fit in ints when gzprint() compiled old style +- Add dummy name before $(SHAREDLIBV) in Makefile [Bar-Lev, Bowler] +- Delete line in configure that adds -L. libz.a to LDFLAGS [Weigelt] +- Add debug records in assembler code [Londer] +- Update RFC references to use http://tools.ietf.org/html/... [Li] +- Add --archs option, use of libtool to configure for Mac OS X [Borstel] + +Changes in 1.2.5 (19 Apr 2010) +- Disable visibility attribute in win32/Makefile.gcc [Bar-Lev] +- Default to libdir as sharedlibdir in configure [Nieder] +- Update copyright dates on modified source files +- Update trees.c to be able to generate modified trees.h +- Exit configure for MinGW, suggesting win32/Makefile.gcc +- Check for NULL path in gz_open [Homurlu] + +Changes in 1.2.4.5 (18 Apr 2010) +- Set sharedlibdir in configure [Torok] +- Set LDFLAGS in Makefile.in [Bar-Lev] +- Avoid mkdir objs race condition in Makefile.in [Bowler] +- Add ZLIB_INTERNAL in front of internal inter-module functions and arrays +- Define ZLIB_INTERNAL to hide internal functions and arrays for GNU C +- Don't use hidden attribute when it is a warning generator (e.g. Solaris) + +Changes in 1.2.4.4 (18 Apr 2010) +- Fix CROSS_PREFIX executable testing, CHOST extract, mingw* [Torok] +- Undefine _LARGEFILE64_SOURCE in zconf.h if it is zero, but not if empty +- Try to use bash or ksh regardless of functionality of /bin/sh +- Fix configure incompatibility with NetBSD sh +- Remove attempt to run under bash or ksh since have better NetBSD fix +- Fix win32/Makefile.gcc for MinGW [Bar-Lev] +- Add diagnostic messages when using CROSS_PREFIX in configure +- Added --sharedlibdir option to configure [Weigelt] +- Use hidden visibility attribute when available [Frysinger] + +Changes in 1.2.4.3 (10 Apr 2010) +- Only use CROSS_PREFIX in configure for ar and ranlib if they exist +- Use CROSS_PREFIX for nm [Bar-Lev] +- Assume _LARGEFILE64_SOURCE defined is equivalent to true +- Avoid use of undefined symbols in #if with && and || +- Make *64 prototypes in gzguts.h consistent with functions +- Add -shared load option for MinGW in configure [Bowler] +- Move z_off64_t to public interface, use instead of off64_t +- Remove ! from shell test in configure (not portable to Solaris) +- Change +0 macro tests to -0 for possibly increased portability + +Changes in 1.2.4.2 (9 Apr 2010) +- Add consistent carriage returns to readme.txt's in masmx86 and masmx64 +- Really provide prototypes for *64 functions when building without LFS +- Only define unlink() in minigzip.c if unistd.h not included +- Update README to point to contrib/vstudio project files +- Move projects/vc6 to old/ and remove projects/ +- Include stdlib.h in minigzip.c for setmode() definition under WinCE +- Clean up assembler builds in win32/Makefile.msc [Rowe] +- Include sys/types.h for Microsoft for off_t definition +- Fix memory leak on error in gz_open() +- Symbolize nm as $NM in configure [Weigelt] +- Use TEST_LDSHARED instead of LDSHARED to link test programs [Weigelt] +- Add +0 to _FILE_OFFSET_BITS and _LFS64_LARGEFILE in case not defined +- Fix bug in gzeof() to take into account unused input data +- Avoid initialization of structures with variables in puff.c +- Updated win32/README-WIN32.txt [Rowe] + +Changes in 1.2.4.1 (28 Mar 2010) +- Remove the use of [a-z] constructs for sed in configure [gentoo 310225] +- Remove $(SHAREDLIB) from LIBS in Makefile.in [Creech] +- Restore "for debugging" comment on sprintf() in gzlib.c +- Remove fdopen for MVS from gzguts.h +- Put new README-WIN32.txt in win32 [Rowe] +- Add check for shell to configure and invoke another shell if needed +- Fix big fat stinking bug in gzseek() on uncompressed files +- Remove vestigial F_OPEN64 define in zutil.h +- Set and check the value of _LARGEFILE_SOURCE and _LARGEFILE64_SOURCE +- Avoid errors on non-LFS systems when applications define LFS macros +- Set EXE to ".exe" in configure for MINGW [Kahle] +- Match crc32() in crc32.c exactly to the prototype in zlib.h [Sherrill] +- Add prefix for cross-compilation in win32/makefile.gcc [Bar-Lev] +- Add DLL install in win32/makefile.gcc [Bar-Lev] +- Allow Linux* or linux* from uname in configure [Bar-Lev] +- Allow ldconfig to be redefined in configure and Makefile.in [Bar-Lev] +- Add cross-compilation prefixes to configure [Bar-Lev] +- Match type exactly in gz_load() invocation in gzread.c +- Match type exactly of zcalloc() in zutil.c to zlib.h alloc_func +- Provide prototypes for *64 functions when building zlib without LFS +- Don't use -lc when linking shared library on MinGW +- Remove errno.h check in configure and vestigial errno code in zutil.h + +Changes in 1.2.4 (14 Mar 2010) +- Fix VER3 extraction in configure for no fourth subversion +- Update zlib.3, add docs to Makefile.in to make .pdf out of it +- Add zlib.3.pdf to distribution +- Don't set error code in gzerror() if passed pointer is NULL +- Apply destination directory fixes to CMakeLists.txt [Lowman] +- Move #cmakedefine's to a new zconf.in.cmakein +- Restore zconf.h for builds that don't use configure or cmake +- Add distclean to dummy Makefile for convenience +- Update and improve INDEX, README, and FAQ +- Update CMakeLists.txt for the return of zconf.h [Lowman] +- Update contrib/vstudio/vc9 and vc10 [Vollant] +- Change libz.dll.a back to libzdll.a in win32/Makefile.gcc +- Apply license and readme changes to contrib/asm686 [Raiter] +- Check file name lengths and add -c option in minigzip.c [Li] +- Update contrib/amd64 and contrib/masmx86/ [Vollant] +- Avoid use of "eof" parameter in trees.c to not shadow library variable +- Update make_vms.com for removal of zlibdefs.h [Zinser] +- Update assembler code and vstudio projects in contrib [Vollant] +- Remove outdated assembler code contrib/masm686 and contrib/asm586 +- Remove old vc7 and vc8 from contrib/vstudio +- Update win32/Makefile.msc, add ZLIB_VER_SUBREVISION [Rowe] +- Fix memory leaks in gzclose_r() and gzclose_w(), file leak in gz_open() +- Add contrib/gcc_gvmat64 for longest_match and inflate_fast [Vollant] +- Remove *64 functions from win32/zlib.def (they're not 64-bit yet) +- Fix bug in void-returning vsprintf() case in gzwrite.c +- Fix name change from inflate.h in contrib/inflate86/inffas86.c +- Check if temporary file exists before removing in make_vms.com [Zinser] +- Fix make install and uninstall for --static option +- Fix usage of _MSC_VER in gzguts.h and zutil.h [Truta] +- Update readme.txt in contrib/masmx64 and masmx86 to assemble + +Changes in 1.2.3.9 (21 Feb 2010) +- Expunge gzio.c +- Move as400 build information to old +- Fix updates in contrib/minizip and contrib/vstudio +- Add const to vsnprintf test in configure to avoid warnings [Weigelt] +- Delete zconf.h (made by configure) [Weigelt] +- Change zconf.in.h to zconf.h.in per convention [Weigelt] +- Check for NULL buf in gzgets() +- Return empty string for gzgets() with len == 1 (like fgets()) +- Fix description of gzgets() in zlib.h for end-of-file, NULL return +- Update minizip to 1.1 [Vollant] +- Avoid MSVC loss of data warnings in gzread.c, gzwrite.c +- Note in zlib.h that gzerror() should be used to distinguish from EOF +- Remove use of snprintf() from gzlib.c +- Fix bug in gzseek() +- Update contrib/vstudio, adding vc9 and vc10 [Kuno, Vollant] +- Fix zconf.h generation in CMakeLists.txt [Lowman] +- Improve comments in zconf.h where modified by configure + +Changes in 1.2.3.8 (13 Feb 2010) +- Clean up text files (tabs, trailing whitespace, etc.) [Oberhumer] +- Use z_off64_t in gz_zero() and gz_skip() to match state->skip +- Avoid comparison problem when sizeof(int) == sizeof(z_off64_t) +- Revert to Makefile.in from 1.2.3.6 (live with the clutter) +- Fix missing error return in gzflush(), add zlib.h note +- Add *64 functions to zlib.map [Levin] +- Fix signed/unsigned comparison in gz_comp() +- Use SFLAGS when testing shared linking in configure +- Add --64 option to ./configure to use -m64 with gcc +- Fix ./configure --help to correctly name options +- Have make fail if a test fails [Levin] +- Avoid buffer overrun in contrib/masmx64/gvmat64.asm [Simpson] +- Remove assembler object files from contrib + +Changes in 1.2.3.7 (24 Jan 2010) +- Always gzopen() with O_LARGEFILE if available +- Fix gzdirect() to work immediately after gzopen() or gzdopen() +- Make gzdirect() more precise when the state changes while reading +- Improve zlib.h documentation in many places +- Catch memory allocation failure in gz_open() +- Complete close operation if seek forward in gzclose_w() fails +- Return Z_ERRNO from gzclose_r() if close() fails +- Return Z_STREAM_ERROR instead of EOF for gzclose() being passed NULL +- Return zero for gzwrite() errors to match zlib.h description +- Return -1 on gzputs() error to match zlib.h description +- Add zconf.in.h to allow recovery from configure modification [Weigelt] +- Fix static library permissions in Makefile.in [Weigelt] +- Avoid warnings in configure tests that hide functionality [Weigelt] +- Add *BSD and DragonFly to Linux case in configure [gentoo 123571] +- Change libzdll.a to libz.dll.a in win32/Makefile.gcc [gentoo 288212] +- Avoid access of uninitialized data for first inflateReset2 call [Gomes] +- Keep object files in subdirectories to reduce the clutter somewhat +- Remove default Makefile and zlibdefs.h, add dummy Makefile +- Add new external functions to Z_PREFIX, remove duplicates, z_z_ -> z_ +- Remove zlibdefs.h completely -- modify zconf.h instead + +Changes in 1.2.3.6 (17 Jan 2010) +- Avoid void * arithmetic in gzread.c and gzwrite.c +- Make compilers happier with const char * for gz_error message +- Avoid unused parameter warning in inflate.c +- Avoid signed-unsigned comparison warning in inflate.c +- Indent #pragma's for traditional C +- Fix usage of strwinerror() in glib.c, change to gz_strwinerror() +- Correct email address in configure for system options +- Update make_vms.com and add make_vms.com to contrib/minizip [Zinser] +- Update zlib.map [Brown] +- Fix Makefile.in for Solaris 10 make of example64 and minizip64 [Torok] +- Apply various fixes to CMakeLists.txt [Lowman] +- Add checks on len in gzread() and gzwrite() +- Add error message for no more room for gzungetc() +- Remove zlib version check in gzwrite() +- Defer compression of gzprintf() result until need to +- Use snprintf() in gzdopen() if available +- Remove USE_MMAP configuration determination (only used by minigzip) +- Remove examples/pigz.c (available separately) +- Update examples/gun.c to 1.6 + +Changes in 1.2.3.5 (8 Jan 2010) +- Add space after #if in zutil.h for some compilers +- Fix relatively harmless bug in deflate_fast() [Exarevsky] +- Fix same problem in deflate_slow() +- Add $(SHAREDLIBV) to LIBS in Makefile.in [Brown] +- Add deflate_rle() for faster Z_RLE strategy run-length encoding +- Add deflate_huff() for faster Z_HUFFMAN_ONLY encoding +- Change name of "write" variable in inffast.c to avoid library collisions +- Fix premature EOF from gzread() in gzio.c [Brown] +- Use zlib header window size if windowBits is 0 in inflateInit2() +- Remove compressBound() call in deflate.c to avoid linking compress.o +- Replace use of errno in gz* with functions, support WinCE [Alves] +- Provide alternative to perror() in minigzip.c for WinCE [Alves] +- Don't use _vsnprintf on later versions of MSVC [Lowman] +- Add CMake build script and input file [Lowman] +- Update contrib/minizip to 1.1 [Svensson, Vollant] +- Moved nintendods directory from contrib to root +- Replace gzio.c with a new set of routines with the same functionality +- Add gzbuffer(), gzoffset(), gzclose_r(), gzclose_w() as part of above +- Update contrib/minizip to 1.1b +- Change gzeof() to return 0 on error instead of -1 to agree with zlib.h + +Changes in 1.2.3.4 (21 Dec 2009) +- Use old school .SUFFIXES in Makefile.in for FreeBSD compatibility +- Update comments in configure and Makefile.in for default --shared +- Fix test -z's in configure [Marquess] +- Build examplesh and minigzipsh when not testing +- Change NULL's to Z_NULL's in deflate.c and in comments in zlib.h +- Import LDFLAGS from the environment in configure +- Fix configure to populate SFLAGS with discovered CFLAGS options +- Adapt make_vms.com to the new Makefile.in [Zinser] +- Add zlib2ansi script for C++ compilation [Marquess] +- Add _FILE_OFFSET_BITS=64 test to make test (when applicable) +- Add AMD64 assembler code for longest match to contrib [Teterin] +- Include options from $SFLAGS when doing $LDSHARED +- Simplify 64-bit file support by introducing z_off64_t type +- Make shared object files in objs directory to work around old Sun cc +- Use only three-part version number for Darwin shared compiles +- Add rc option to ar in Makefile.in for when ./configure not run +- Add -WI,-rpath,. to LDFLAGS for OSF 1 V4* +- Set LD_LIBRARYN32_PATH for SGI IRIX shared compile +- Protect against _FILE_OFFSET_BITS being defined when compiling zlib +- Rename Makefile.in targets allstatic to static and allshared to shared +- Fix static and shared Makefile.in targets to be independent +- Correct error return bug in gz_open() by setting state [Brown] +- Put spaces before ;;'s in configure for better sh compatibility +- Add pigz.c (parallel implementation of gzip) to examples/ +- Correct constant in crc32.c to UL [Leventhal] +- Reject negative lengths in crc32_combine() +- Add inflateReset2() function to work like inflateEnd()/inflateInit2() +- Include sys/types.h for _LARGEFILE64_SOURCE [Brown] +- Correct typo in doc/algorithm.txt [Janik] +- Fix bug in adler32_combine() [Zhu] +- Catch missing-end-of-block-code error in all inflates and in puff + Assures that random input to inflate eventually results in an error +- Added enough.c (calculation of ENOUGH for inftrees.h) to examples/ +- Update ENOUGH and its usage to reflect discovered bounds +- Fix gzerror() error report on empty input file [Brown] +- Add ush casts in trees.c to avoid pedantic runtime errors +- Fix typo in zlib.h uncompress() description [Reiss] +- Correct inflate() comments with regard to automatic header detection +- Remove deprecation comment on Z_PARTIAL_FLUSH (it stays) +- Put new version of gzlog (2.0) in examples with interruption recovery +- Add puff compile option to permit invalid distance-too-far streams +- Add puff TEST command options, ability to read piped input +- Prototype the *64 functions in zlib.h when _FILE_OFFSET_BITS == 64, but + _LARGEFILE64_SOURCE not defined +- Fix Z_FULL_FLUSH to truly erase the past by resetting s->strstart +- Fix deflateSetDictionary() to use all 32K for output consistency +- Remove extraneous #define MIN_LOOKAHEAD in deflate.c (in deflate.h) +- Clear bytes after deflate lookahead to avoid use of uninitialized data +- Change a limit in inftrees.c to be more transparent to Coverity Prevent +- Update win32/zlib.def with exported symbols from zlib.h +- Correct spelling errors in zlib.h [Willem, Sobrado] +- Allow Z_BLOCK for deflate() to force a new block +- Allow negative bits in inflatePrime() to delete existing bit buffer +- Add Z_TREES flush option to inflate() to return at end of trees +- Add inflateMark() to return current state information for random access +- Add Makefile for NintendoDS to contrib [Costa] +- Add -w in configure compile tests to avoid spurious warnings [Beucler] +- Fix typos in zlib.h comments for deflateSetDictionary() +- Fix EOF detection in transparent gzread() [Maier] + +Changes in 1.2.3.3 (2 October 2006) +- Make --shared the default for configure, add a --static option +- Add compile option to permit invalid distance-too-far streams +- Add inflateUndermine() function which is required to enable above +- Remove use of "this" variable name for C++ compatibility [Marquess] +- Add testing of shared library in make test, if shared library built +- Use ftello() and fseeko() if available instead of ftell() and fseek() +- Provide two versions of all functions that use the z_off_t type for + binary compatibility -- a normal version and a 64-bit offset version, + per the Large File Support Extension when _LARGEFILE64_SOURCE is + defined; use the 64-bit versions by default when _FILE_OFFSET_BITS + is defined to be 64 +- Add a --uname= option to configure to perhaps help with cross-compiling + +Changes in 1.2.3.2 (3 September 2006) +- Turn off silly Borland warnings [Hay] +- Use off64_t and define _LARGEFILE64_SOURCE when present +- Fix missing dependency on inffixed.h in Makefile.in +- Rig configure --shared to build both shared and static [Teredesai, Truta] +- Remove zconf.in.h and instead create a new zlibdefs.h file +- Fix contrib/minizip/unzip.c non-encrypted after encrypted [Vollant] +- Add treebuild.xml (see http://treebuild.metux.de/) [Weigelt] + +Changes in 1.2.3.1 (16 August 2006) +- Add watcom directory with OpenWatcom make files [Daniel] +- Remove #undef of FAR in zconf.in.h for MVS [Fedtke] +- Update make_vms.com [Zinser] +- Use -fPIC for shared build in configure [Teredesai, Nicholson] +- Use only major version number for libz.so on IRIX and OSF1 [Reinholdtsen] +- Use fdopen() (not _fdopen()) for Interix in zutil.h [Bäck] +- Add some FAQ entries about the contrib directory +- Update the MVS question in the FAQ +- Avoid extraneous reads after EOF in gzio.c [Brown] +- Correct spelling of "successfully" in gzio.c [Randers-Pehrson] +- Add comments to zlib.h about gzerror() usage [Brown] +- Set extra flags in gzip header in gzopen() like deflate() does +- Make configure options more compatible with double-dash conventions + [Weigelt] +- Clean up compilation under Solaris SunStudio cc [Rowe, Reinholdtsen] +- Fix uninstall target in Makefile.in [Truta] +- Add pkgconfig support [Weigelt] +- Use $(DESTDIR) macro in Makefile.in [Reinholdtsen, Weigelt] +- Replace set_data_type() with a more accurate detect_data_type() in + trees.c, according to the txtvsbin.txt document [Truta] +- Swap the order of #include and #include "zlib.h" in + gzio.c, example.c and minigzip.c [Truta] +- Shut up annoying VS2005 warnings about standard C deprecation [Rowe, + Truta] (where?) +- Fix target "clean" from win32/Makefile.bor [Truta] +- Create .pdb and .manifest files in win32/makefile.msc [Ziegler, Rowe] +- Update zlib www home address in win32/DLL_FAQ.txt [Truta] +- Update contrib/masmx86/inffas32.asm for VS2005 [Vollant, Van Wassenhove] +- Enable browse info in the "Debug" and "ASM Debug" configurations in + the Visual C++ 6 project, and set (non-ASM) "Debug" as default [Truta] +- Add pkgconfig support [Weigelt] +- Add ZLIB_VER_MAJOR, ZLIB_VER_MINOR and ZLIB_VER_REVISION in zlib.h, + for use in win32/zlib1.rc [Polushin, Rowe, Truta] +- Add a document that explains the new text detection scheme to + doc/txtvsbin.txt [Truta] +- Add rfc1950.txt, rfc1951.txt and rfc1952.txt to doc/ [Truta] +- Move algorithm.txt into doc/ [Truta] +- Synchronize FAQ with website +- Fix compressBound(), was low for some pathological cases [Fearnley] +- Take into account wrapper variations in deflateBound() +- Set examples/zpipe.c input and output to binary mode for Windows +- Update examples/zlib_how.html with new zpipe.c (also web site) +- Fix some warnings in examples/gzlog.c and examples/zran.c (it seems + that gcc became pickier in 4.0) +- Add zlib.map for Linux: "All symbols from zlib-1.1.4 remain + un-versioned, the patch adds versioning only for symbols introduced in + zlib-1.2.0 or later. It also declares as local those symbols which are + not designed to be exported." [Levin] +- Update Z_PREFIX list in zconf.in.h, add --zprefix option to configure +- Do not initialize global static by default in trees.c, add a response + NO_INIT_GLOBAL_POINTERS to initialize them if needed [Marquess] +- Don't use strerror() in gzio.c under WinCE [Yakimov] +- Don't use errno.h in zutil.h under WinCE [Yakimov] +- Move arguments for AR to its usage to allow replacing ar [Marot] +- Add HAVE_VISIBILITY_PRAGMA in zconf.in.h for Mozilla [Randers-Pehrson] +- Improve inflateInit() and inflateInit2() documentation +- Fix structure size comment in inflate.h +- Change configure help option from --h* to --help [Santos] + +Changes in 1.2.3 (18 July 2005) +- Apply security vulnerability fixes to contrib/infback9 as well +- Clean up some text files (carriage returns, trailing space) +- Update testzlib, vstudio, masmx64, and masmx86 in contrib [Vollant] + +Changes in 1.2.2.4 (11 July 2005) +- Add inflatePrime() function for starting inflation at bit boundary +- Avoid some Visual C warnings in deflate.c +- Avoid more silly Visual C warnings in inflate.c and inftrees.c for 64-bit + compile +- Fix some spelling errors in comments [Betts] +- Correct inflateInit2() error return documentation in zlib.h +- Add zran.c example of compressed data random access to examples + directory, shows use of inflatePrime() +- Fix cast for assignments to strm->state in inflate.c and infback.c +- Fix zlibCompileFlags() in zutil.c to use 1L for long shifts [Oberhumer] +- Move declarations of gf2 functions to right place in crc32.c [Oberhumer] +- Add cast in trees.c t avoid a warning [Oberhumer] +- Avoid some warnings in fitblk.c, gun.c, gzjoin.c in examples [Oberhumer] +- Update make_vms.com [Zinser] +- Initialize state->write in inflateReset() since copied in inflate_fast() +- Be more strict on incomplete code sets in inflate_table() and increase + ENOUGH and MAXD -- this repairs a possible security vulnerability for + invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for + discovering the vulnerability and providing test cases +- Add ia64 support to configure for HP-UX [Smith] +- Add error return to gzread() for format or i/o error [Levin] +- Use malloc.h for OS/2 [Necasek] + +Changes in 1.2.2.3 (27 May 2005) +- Replace 1U constants in inflate.c and inftrees.c for 64-bit compile +- Typecast fread() return values in gzio.c [Vollant] +- Remove trailing space in minigzip.c outmode (VC++ can't deal with it) +- Fix crc check bug in gzread() after gzungetc() [Heiner] +- Add the deflateTune() function to adjust internal compression parameters +- Add a fast gzip decompressor, gun.c, to examples (use of inflateBack) +- Remove an incorrect assertion in examples/zpipe.c +- Add C++ wrapper in infback9.h [Donais] +- Fix bug in inflateCopy() when decoding fixed codes +- Note in zlib.h how much deflateSetDictionary() actually uses +- Remove USE_DICT_HEAD in deflate.c (would mess up inflate if used) +- Add _WIN32_WCE to define WIN32 in zconf.in.h [Spencer] +- Don't include stderr.h or errno.h for _WIN32_WCE in zutil.h [Spencer] +- Add gzdirect() function to indicate transparent reads +- Update contrib/minizip [Vollant] +- Fix compilation of deflate.c when both ASMV and FASTEST [Oberhumer] +- Add casts in crc32.c to avoid warnings [Oberhumer] +- Add contrib/masmx64 [Vollant] +- Update contrib/asm586, asm686, masmx86, testzlib, vstudio [Vollant] + +Changes in 1.2.2.2 (30 December 2004) +- Replace structure assignments in deflate.c and inflate.c with zmemcpy to + avoid implicit memcpy calls (portability for no-library compilation) +- Increase sprintf() buffer size in gzdopen() to allow for large numbers +- Add INFLATE_STRICT to check distances against zlib header +- Improve WinCE errno handling and comments [Chang] +- Remove comment about no gzip header processing in FAQ +- Add Z_FIXED strategy option to deflateInit2() to force fixed trees +- Add updated make_vms.com [Coghlan], update README +- Create a new "examples" directory, move gzappend.c there, add zpipe.c, + fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html +- Add FAQ entry and comments in deflate.c on uninitialized memory access +- Add Solaris 9 make options in configure [Gilbert] +- Allow strerror() usage in gzio.c for STDC +- Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer] +- Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant] +- Use z_off_t for adler32_combine() and crc32_combine() lengths +- Make adler32() much faster for small len +- Use OS_CODE in deflate() default gzip header + +Changes in 1.2.2.1 (31 October 2004) +- Allow inflateSetDictionary() call for raw inflate +- Fix inflate header crc check bug for file names and comments +- Add deflateSetHeader() and gz_header structure for custom gzip headers +- Add inflateGetheader() to retrieve gzip headers +- Add crc32_combine() and adler32_combine() functions +- Add alloc_func, free_func, in_func, out_func to Z_PREFIX list +- Use zstreamp consistently in zlib.h (inflate_back functions) +- Remove GUNZIP condition from definition of inflate_mode in inflate.h + and in contrib/inflate86/inffast.S [Truta, Anderson] +- Add support for AMD64 in contrib/inflate86/inffas86.c [Anderson] +- Update projects/README.projects and projects/visualc6 [Truta] +- Update win32/DLL_FAQ.txt [Truta] +- Avoid warning under NO_GZCOMPRESS in gzio.c; fix typo [Truta] +- Deprecate Z_ASCII; use Z_TEXT instead [Truta] +- Use a new algorithm for setting strm->data_type in trees.c [Truta] +- Do not define an exit() prototype in zutil.c unless DEBUG defined +- Remove prototype of exit() from zutil.c, example.c, minigzip.c [Truta] +- Add comment in zlib.h for Z_NO_FLUSH parameter to deflate() +- Fix Darwin build version identification [Peterson] + +Changes in 1.2.2 (3 October 2004) +- Update zlib.h comments on gzip in-memory processing +- Set adler to 1 in inflateReset() to support Java test suite [Walles] +- Add contrib/dotzlib [Ravn] +- Update win32/DLL_FAQ.txt [Truta] +- Update contrib/minizip [Vollant] +- Move contrib/visual-basic.txt to old/ [Truta] +- Fix assembler builds in projects/visualc6/ [Truta] + +Changes in 1.2.1.2 (9 September 2004) +- Update INDEX file +- Fix trees.c to update strm->data_type (no one ever noticed!) +- Fix bug in error case in inflate.c, infback.c, and infback9.c [Brown] +- Add "volatile" to crc table flag declaration (for DYNAMIC_CRC_TABLE) +- Add limited multitasking protection to DYNAMIC_CRC_TABLE +- Add NO_vsnprintf for VMS in zutil.h [Mozilla] +- Don't declare strerror() under VMS [Mozilla] +- Add comment to DYNAMIC_CRC_TABLE to use get_crc_table() to initialize +- Update contrib/ada [Anisimkov] +- Update contrib/minizip [Vollant] +- Fix configure to not hardcode directories for Darwin [Peterson] +- Fix gzio.c to not return error on empty files [Brown] +- Fix indentation; update version in contrib/delphi/ZLib.pas and + contrib/pascal/zlibpas.pas [Truta] +- Update mkasm.bat in contrib/masmx86 [Truta] +- Update contrib/untgz [Truta] +- Add projects/README.projects [Truta] +- Add project for MS Visual C++ 6.0 in projects/visualc6 [Cadieux, Truta] +- Update win32/DLL_FAQ.txt [Truta] +- Update list of Z_PREFIX symbols in zconf.h [Randers-Pehrson, Truta] +- Remove an unnecessary assignment to curr in inftrees.c [Truta] +- Add OS/2 to exe builds in configure [Poltorak] +- Remove err dummy parameter in zlib.h [Kientzle] + +Changes in 1.2.1.1 (9 January 2004) +- Update email address in README +- Several FAQ updates +- Fix a big fat bug in inftrees.c that prevented decoding valid + dynamic blocks with only literals and no distance codes -- + Thanks to "Hot Emu" for the bug report and sample file +- Add a note to puff.c on no distance codes case + +Changes in 1.2.1 (17 November 2003) +- Remove a tab in contrib/gzappend/gzappend.c +- Update some interfaces in contrib for new zlib functions +- Update zlib version number in some contrib entries +- Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta] +- Support shared libraries on Hurd and KFreeBSD [Brown] +- Fix error in NO_DIVIDE option of adler32.c + +Changes in 1.2.0.8 (4 November 2003) +- Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas +- Add experimental NO_DIVIDE #define in adler32.c + - Possibly faster on some processors (let me know if it is) +- Correct Z_BLOCK to not return on first inflate call if no wrap +- Fix strm->data_type on inflate() return to correctly indicate EOB +- Add deflatePrime() function for appending in the middle of a byte +- Add contrib/gzappend for an example of appending to a stream +- Update win32/DLL_FAQ.txt [Truta] +- Delete Turbo C comment in README [Truta] +- Improve some indentation in zconf.h [Truta] +- Fix infinite loop on bad input in configure script [Church] +- Fix gzeof() for concatenated gzip files [Johnson] +- Add example to contrib/visual-basic.txt [Michael B.] +- Add -p to mkdir's in Makefile.in [vda] +- Fix configure to properly detect presence or lack of printf functions +- Add AS400 support [Monnerat] +- Add a little Cygwin support [Wilson] + +Changes in 1.2.0.7 (21 September 2003) +- Correct some debug formats in contrib/infback9 +- Cast a type in a debug statement in trees.c +- Change search and replace delimiter in configure from % to # [Beebe] +- Update contrib/untgz to 0.2 with various fixes [Truta] +- Add build support for Amiga [Nikl] +- Remove some directories in old that have been updated to 1.2 +- Add dylib building for Mac OS X in configure and Makefile.in +- Remove old distribution stuff from Makefile +- Update README to point to DLL_FAQ.txt, and add comment on Mac OS X +- Update links in README + +Changes in 1.2.0.6 (13 September 2003) +- Minor FAQ updates +- Update contrib/minizip to 1.00 [Vollant] +- Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta] +- Update POSTINC comment for 68060 [Nikl] +- Add contrib/infback9 with deflate64 decoding (unsupported) +- For MVS define NO_vsnprintf and undefine FAR [van Burik] +- Add pragma for fdopen on MVS [van Burik] + +Changes in 1.2.0.5 (8 September 2003) +- Add OF to inflateBackEnd() declaration in zlib.h +- Remember start when using gzdopen in the middle of a file +- Use internal off_t counters in gz* functions to properly handle seeks +- Perform more rigorous check for distance-too-far in inffast.c +- Add Z_BLOCK flush option to return from inflate at block boundary +- Set strm->data_type on return from inflate + - Indicate bits unused, if at block boundary, and if in last block +- Replace size_t with ptrdiff_t in crc32.c, and check for correct size +- Add condition so old NO_DEFLATE define still works for compatibility +- FAQ update regarding the Windows DLL [Truta] +- INDEX update: add qnx entry, remove aix entry [Truta] +- Install zlib.3 into mandir [Wilson] +- Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta] +- Adapt the zlib interface to the new DLL convention guidelines [Truta] +- Introduce ZLIB_WINAPI macro to allow the export of functions using + the WINAPI calling convention, for Visual Basic [Vollant, Truta] +- Update msdos and win32 scripts and makefiles [Truta] +- Export symbols by name, not by ordinal, in win32/zlib.def [Truta] +- Add contrib/ada [Anisimkov] +- Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta] +- Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant] +- Add contrib/masm686 [Truta] +- Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm + [Truta, Vollant] +- Update contrib/delphi; rename to contrib/pascal; add example [Truta] +- Remove contrib/delphi2; add a new contrib/delphi [Truta] +- Avoid inclusion of the nonstandard in contrib/iostream, + and fix some method prototypes [Truta] +- Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip + [Truta] +- Avoid the use of backslash (\) in contrib/minizip [Vollant] +- Fix file time handling in contrib/untgz; update makefiles [Truta] +- Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines + [Vollant] +- Remove contrib/vstudio/vc15_16 [Vollant] +- Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta] +- Update README.contrib [Truta] +- Invert the assignment order of match_head and s->prev[...] in + INSERT_STRING [Truta] +- Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings + [Truta] +- Compare function pointers with 0, not with NULL or Z_NULL [Truta] +- Fix prototype of syncsearch in inflate.c [Truta] +- Introduce ASMINF macro to be enabled when using an ASM implementation + of inflate_fast [Truta] +- Change NO_DEFLATE to NO_GZCOMPRESS [Truta] +- Modify test_gzio in example.c to take a single file name as a + parameter [Truta] +- Exit the example.c program if gzopen fails [Truta] +- Add type casts around strlen in example.c [Truta] +- Remove casting to sizeof in minigzip.c; give a proper type + to the variable compared with SUFFIX_LEN [Truta] +- Update definitions of STDC and STDC99 in zconf.h [Truta] +- Synchronize zconf.h with the new Windows DLL interface [Truta] +- Use SYS16BIT instead of __32BIT__ to distinguish between + 16- and 32-bit platforms [Truta] +- Use far memory allocators in small 16-bit memory models for + Turbo C [Truta] +- Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in + zlibCompileFlags [Truta] +- Cygwin has vsnprintf [Wilson] +- In Windows16, OS_CODE is 0, as in MSDOS [Truta] +- In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson] + +Changes in 1.2.0.4 (10 August 2003) +- Minor FAQ updates +- Be more strict when checking inflateInit2's windowBits parameter +- Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well +- Add gzip wrapper option to deflateInit2 using windowBits +- Add updated QNX rule in configure and qnx directory [Bonnefoy] +- Make inflate distance-too-far checks more rigorous +- Clean up FAR usage in inflate +- Add casting to sizeof() in gzio.c and minigzip.c + +Changes in 1.2.0.3 (19 July 2003) +- Fix silly error in gzungetc() implementation [Vollant] +- Update contrib/minizip and contrib/vstudio [Vollant] +- Fix printf format in example.c +- Correct cdecl support in zconf.in.h [Anisimkov] +- Minor FAQ updates + +Changes in 1.2.0.2 (13 July 2003) +- Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons +- Attempt to avoid warnings in crc32.c for pointer-int conversion +- Add AIX to configure, remove aix directory [Bakker] +- Add some casts to minigzip.c +- Improve checking after insecure sprintf() or vsprintf() calls +- Remove #elif's from crc32.c +- Change leave label to inf_leave in inflate.c and infback.c to avoid + library conflicts +- Remove inflate gzip decoding by default--only enable gzip decoding by + special request for stricter backward compatibility +- Add zlibCompileFlags() function to return compilation information +- More typecasting in deflate.c to avoid warnings +- Remove leading underscore from _Capital #defines [Truta] +- Fix configure to link shared library when testing +- Add some Windows CE target adjustments [Mai] +- Remove #define ZLIB_DLL in zconf.h [Vollant] +- Add zlib.3 [Rodgers] +- Update RFC URL in deflate.c and algorithm.txt [Mai] +- Add zlib_dll_FAQ.txt to contrib [Truta] +- Add UL to some constants [Truta] +- Update minizip and vstudio [Vollant] +- Remove vestigial NEED_DUMMY_RETURN from zconf.in.h +- Expand use of NO_DUMMY_DECL to avoid all dummy structures +- Added iostream3 to contrib [Schwardt] +- Replace rewind() with fseek() for WinCE [Truta] +- Improve setting of zlib format compression level flags + - Report 0 for huffman and rle strategies and for level == 0 or 1 + - Report 2 only for level == 6 +- Only deal with 64K limit when necessary at compile time [Truta] +- Allow TOO_FAR check to be turned off at compile time [Truta] +- Add gzclearerr() function [Souza] +- Add gzungetc() function + +Changes in 1.2.0.1 (17 March 2003) +- Add Z_RLE strategy for run-length encoding [Truta] + - When Z_RLE requested, restrict matches to distance one + - Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE +- Correct FASTEST compilation to allow level == 0 +- Clean up what gets compiled for FASTEST +- Incorporate changes to zconf.in.h [Vollant] + - Refine detection of Turbo C need for dummy returns + - Refine ZLIB_DLL compilation + - Include additional header file on VMS for off_t typedef +- Try to use _vsnprintf where it supplants vsprintf [Vollant] +- Add some casts in inffast.c +- Enhance comments in zlib.h on what happens if gzprintf() tries to + write more than 4095 bytes before compression +- Remove unused state from inflateBackEnd() +- Remove exit(0) from minigzip.c, example.c +- Get rid of all those darn tabs +- Add "check" target to Makefile.in that does the same thing as "test" +- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in +- Update contrib/inflate86 [Anderson] +- Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant] +- Add msdos and win32 directories with makefiles [Truta] +- More additions and improvements to the FAQ + +Changes in 1.2.0 (9 March 2003) +- New and improved inflate code + - About 20% faster + - Does not allocate 32K window unless and until needed + - Automatically detects and decompresses gzip streams + - Raw inflate no longer needs an extra dummy byte at end + - Added inflateBack functions using a callback interface--even faster + than inflate, useful for file utilities (gzip, zip) + - Added inflateCopy() function to record state for random access on + externally generated deflate streams (e.g. in gzip files) + - More readable code (I hope) +- New and improved crc32() + - About 50% faster, thanks to suggestions from Rodney Brown +- Add deflateBound() and compressBound() functions +- Fix memory leak in deflateInit2() +- Permit setting dictionary for raw deflate (for parallel deflate) +- Fix const declaration for gzwrite() +- Check for some malloc() failures in gzio.c +- Fix bug in gzopen() on single-byte file 0x1f +- Fix bug in gzread() on concatenated file with 0x1f at end of buffer + and next buffer doesn't start with 0x8b +- Fix uncompress() to return Z_DATA_ERROR on truncated input +- Free memory at end of example.c +- Remove MAX #define in trees.c (conflicted with some libraries) +- Fix static const's in deflate.c, gzio.c, and zutil.[ch] +- Declare malloc() and free() in gzio.c if STDC not defined +- Use malloc() instead of calloc() in zutil.c if int big enough +- Define STDC for AIX +- Add aix/ with approach for compiling shared library on AIX +- Add HP-UX support for shared libraries in configure +- Add OpenUNIX support for shared libraries in configure +- Use $cc instead of gcc to build shared library +- Make prefix directory if needed when installing +- Correct Macintosh avoidance of typedef Byte in zconf.h +- Correct Turbo C memory allocation when under Linux +- Use libz.a instead of -lz in Makefile (assure use of compiled library) +- Update configure to check for snprintf or vsnprintf functions and their + return value, warn during make if using an insecure function +- Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that + is lost when library is used--resolution is to build new zconf.h +- Documentation improvements (in zlib.h): + - Document raw deflate and inflate + - Update RFCs URL + - Point out that zlib and gzip formats are different + - Note that Z_BUF_ERROR is not fatal + - Document string limit for gzprintf() and possible buffer overflow + - Note requirement on avail_out when flushing + - Note permitted values of flush parameter of inflate() +- Add some FAQs (and even answers) to the FAQ +- Add contrib/inflate86/ for x86 faster inflate +- Add contrib/blast/ for PKWare Data Compression Library decompression +- Add contrib/puff/ simple inflate for deflate format description + +Changes in 1.1.4 (11 March 2002) +- ZFREE was repeated on same allocation on some error conditions + This creates a security problem described in + http://www.zlib.org/advisory-2002-03-11.txt +- Returned incorrect error (Z_MEM_ERROR) on some invalid data +- Avoid accesses before window for invalid distances with inflate window + less than 32K +- force windowBits > 8 to avoid a bug in the encoder for a window size + of 256 bytes. (A complete fix will be available in 1.1.5) + +Changes in 1.1.3 (9 July 1998) +- fix "an inflate input buffer bug that shows up on rare but persistent + occasions" (Mark) +- fix gzread and gztell for concatenated .gz files (Didier Le Botlan) +- fix gzseek(..., SEEK_SET) in write mode +- fix crc check after a gzeek (Frank Faubert) +- fix miniunzip when the last entry in a zip file is itself a zip file + (J Lillge) +- add contrib/asm586 and contrib/asm686 (Brian Raiter) + See http://www.muppetlabs.com/~breadbox/software/assembly.html +- add support for Delphi 3 in contrib/delphi (Bob Dellaca) +- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti) +- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren) +- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks) +- added a FAQ file + +- Support gzdopen on Mac with Metrowerks (Jason Linhart) +- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart) +- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young) +- avoid some warnings with Borland C (Tom Tanner) +- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant) +- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant) +- allow several arguments to configure (Tim Mooney, Frodo Looijaard) +- use libdir and includedir in Makefile.in (Tim Mooney) +- support shared libraries on OSF1 V4 (Tim Mooney) +- remove so_locations in "make clean" (Tim Mooney) +- fix maketree.c compilation error (Glenn, Mark) +- Python interface to zlib now in Python 1.5 (Jeremy Hylton) +- new Makefile.riscos (Rich Walker) +- initialize static descriptors in trees.c for embedded targets (Nick Smith) +- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith) +- add the OS/2 files in Makefile.in too (Andrew Zabolotny) +- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane) +- fix maketree.c to allow clean compilation of inffixed.h (Mark) +- fix parameter check in deflateCopy (Gunther Nikl) +- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler) +- Many portability patches by Christian Spieler: + . zutil.c, zutil.h: added "const" for zmem* + . Make_vms.com: fixed some typos + . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists + . msdos/Makefile.msc: remove "default rtl link library" info from obj files + . msdos/Makefile.*: use model-dependent name for the built zlib library + . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc: + new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT) +- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane) +- replace __far with _far for better portability (Christian Spieler, Tom Lane) +- fix test for errno.h in configure (Tim Newsham) + +Changes in 1.1.2 (19 March 98) +- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant) + See http://www.winimage.com/zLibDll/unzip.html +- preinitialize the inflate tables for fixed codes, to make the code + completely thread safe (Mark) +- some simplifications and slight speed-up to the inflate code (Mark) +- fix gzeof on non-compressed files (Allan Schrum) +- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs) +- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn) +- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny) +- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori) +- do not wrap extern "C" around system includes (Tom Lane) +- mention zlib binding for TCL in README (Andreas Kupries) +- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert) +- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson) +- allow "configure --prefix $HOME" (Tim Mooney) +- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson) +- move Makefile.sas to amiga/Makefile.sas + +Changes in 1.1.1 (27 Feb 98) +- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson) +- remove block truncation heuristic which had very marginal effect for zlib + (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the + compression ratio on some files. This also allows inlining _tr_tally for + matches in deflate_slow +- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier) + +Changes in 1.1.0 (24 Feb 98) +- do not return STREAM_END prematurely in inflate (John Bowler) +- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler) +- compile with -DFASTEST to get compression code optimized for speed only +- in minigzip, try mmap'ing the input file first (Miguel Albrecht) +- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain + on Sun but significant on HP) + +- add a pointer to experimental unzip library in README (Gilles Vollant) +- initialize variable gcc in configure (Chris Herborth) + +Changes in 1.0.9 (17 Feb 1998) +- added gzputs and gzgets functions +- do not clear eof flag in gzseek (Mark Diekhans) +- fix gzseek for files in transparent mode (Mark Diekhans) +- do not assume that vsprintf returns the number of bytes written (Jens Krinke) +- replace EXPORT with ZEXPORT to avoid conflict with other programs +- added compress2 in zconf.h, zlib.def, zlib.dnt +- new asm code from Gilles Vollant in contrib/asm386 +- simplify the inflate code (Mark): + . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new() + . ZALLOC the length list in inflate_trees_fixed() instead of using stack + . ZALLOC the value area for huft_build() instead of using stack + . Simplify Z_FINISH check in inflate() + +- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8 +- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi) +- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with + the declaration of FAR (Gilles Vollant) +- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann) +- read_buf buf parameter of type Bytef* instead of charf* +- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout) +- do not redeclare unlink in minigzip.c for WIN32 (John Bowler) +- fix check for presence of directories in "make install" (Ian Willis) + +Changes in 1.0.8 (27 Jan 1998) +- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant) +- fix gzgetc and gzputc for big endian systems (Markus Oberhumer) +- added compress2() to allow setting the compression level +- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong) +- use constant arrays for the static trees in trees.c instead of computing + them at run time (thanks to Ken Raeburn for this suggestion). To create + trees.h, compile with GEN_TREES_H and run "make test" +- check return code of example in "make test" and display result +- pass minigzip command line options to file_compress +- simplifying code of inflateSync to avoid gcc 2.8 bug + +- support CC="gcc -Wall" in configure -s (QingLong) +- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn) +- fix test for shared library support to avoid compiler warnings +- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant) +- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit) +- do not use fdopen for Metrowerks on Mac (Brad Pettit)) +- add checks for gzputc and gzputc in example.c +- avoid warnings in gzio.c and deflate.c (Andreas Kleinert) +- use const for the CRC table (Ken Raeburn) +- fixed "make uninstall" for shared libraries +- use Tracev instead of Trace in infblock.c +- in example.c use correct compressed length for test_sync +- suppress +vnocompatwarnings in configure for HPUX (not always supported) + +Changes in 1.0.7 (20 Jan 1998) +- fix gzseek which was broken in write mode +- return error for gzseek to negative absolute position +- fix configure for Linux (Chun-Chung Chen) +- increase stack space for MSC (Tim Wegner) +- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant) +- define EXPORTVA for gzprintf (Gilles Vollant) +- added man page zlib.3 (Rick Rodgers) +- for contrib/untgz, fix makedir() and improve Makefile + +- check gzseek in write mode in example.c +- allocate extra buffer for seeks only if gzseek is actually called +- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant) +- add inflateSyncPoint in zconf.h +- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def + +Changes in 1.0.6 (19 Jan 1998) +- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and + gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) +- Fix a deflate bug occurring only with compression level 0 (thanks to + Andy Buckler for finding this one) +- In minigzip, pass transparently also the first byte for .Z files +- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() +- check Z_FINISH in inflate (thanks to Marc Schluper) +- Implement deflateCopy (thanks to Adam Costello) +- make static libraries by default in configure, add --shared option +- move MSDOS or Windows specific files to directory msdos +- suppress the notion of partial flush to simplify the interface + (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4) +- suppress history buffer provided by application to simplify the interface + (this feature was not implemented anyway in 1.0.4) +- next_in and avail_in must be initialized before calling inflateInit or + inflateInit2 +- add EXPORT in all exported functions (for Windows DLL) +- added Makefile.nt (thanks to Stephen Williams) +- added the unsupported "contrib" directory: + contrib/asm386/ by Gilles Vollant + 386 asm code replacing longest_match() + contrib/iostream/ by Kevin Ruland + A C++ I/O streams interface to the zlib gz* functions + contrib/iostream2/ by Tyge Løvset + Another C++ I/O streams interface + contrib/untgz/ by "Pedro A. Aranda Guti\irrez" + A very simple tar.gz file extractor using zlib + contrib/visual-basic.txt by Carlos Rios + How to use compress(), uncompress() and the gz* functions from VB +- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression + level) in minigzip (thanks to Tom Lane) + +- use const for rommable constants in deflate +- added test for gzseek and gztell in example.c +- add undocumented function inflateSyncPoint() (hack for Paul Mackerras) +- add undocumented function zError to convert error code to string + (for Tim Smithers) +- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code +- Use default memcpy for Symantec MSDOS compiler +- Add EXPORT keyword for check_func (needed for Windows DLL) +- add current directory to LD_LIBRARY_PATH for "make test" +- create also a link for libz.so.1 +- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura) +- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX) +- added -soname for Linux in configure (Chun-Chung Chen, +- assign numbers to the exported functions in zlib.def (for Windows DLL) +- add advice in zlib.h for best usage of deflateSetDictionary +- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn) +- allow compilation with ANSI keywords only enabled for TurboC in large model +- avoid "versionString"[0] (Borland bug) +- add NEED_DUMMY_RETURN for Borland +- use variable z_verbose for tracing in debug mode (L. Peter Deutsch) +- allow compilation with CC +- defined STDC for OS/2 (David Charlap) +- limit external names to 8 chars for MVS (Thomas Lund) +- in minigzip.c, use static buffers only for 16-bit systems +- fix suffix check for "minigzip -d foo.gz" +- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee) +- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau) +- added makelcc.bat for lcc-win32 (Tom St Denis) +- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe) +- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion +- check for unistd.h in configure (for off_t) +- remove useless check parameter in inflate_blocks_free +- avoid useless assignment of s->check to itself in inflate_blocks_new +- do not flush twice in gzclose (thanks to Ken Raeburn) +- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h +- use NO_ERRNO_H instead of enumeration of operating systems with errno.h +- work around buggy fclose on pipes for HP/UX +- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson) +- fix configure if CC is already equal to gcc + +Changes in 1.0.5 (3 Jan 98) +- Fix inflate to terminate gracefully when fed corrupted or invalid data +- Use const for rommable constants in inflate +- Eliminate memory leaks on error conditions in inflate +- Removed some vestigial code in inflate +- Update web address in README + +Changes in 1.0.4 (24 Jul 96) +- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF + bit, so the decompressor could decompress all the correct data but went + on to attempt decompressing extra garbage data. This affected minigzip too +- zlibVersion and gzerror return const char* (needed for DLL) +- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno) +- use z_error only for DEBUG (avoid problem with DLLs) + +Changes in 1.0.3 (2 Jul 96) +- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS + small and medium models; this makes the library incompatible with previous + versions for these models. (No effect in large model or on other systems.) +- return OK instead of BUF_ERROR if previous deflate call returned with + avail_out as zero but there is nothing to do +- added memcmp for non STDC compilers +- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly) +- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO) +- better check for 16-bit mode MSC (avoids problem with Symantec) + +Changes in 1.0.2 (23 May 96) +- added Windows DLL support +- added a function zlibVersion (for the DLL support) +- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model) +- Bytef is define's instead of typedef'd only for Borland C +- avoid reading uninitialized memory in example.c +- mention in README that the zlib format is now RFC1950 +- updated Makefile.dj2 +- added algorithm.doc + +Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion] +- fix array overlay in deflate.c which sometimes caused bad compressed data +- fix inflate bug with empty stored block +- fix MSDOS medium model which was broken in 0.99 +- fix deflateParams() which could generate bad compressed data +- Bytef is define'd instead of typedef'ed (work around Borland bug) +- added an INDEX file +- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32), + Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas) +- speed up adler32 for modern machines without auto-increment +- added -ansi for IRIX in configure +- static_init_done in trees.c is an int +- define unlink as delete for VMS +- fix configure for QNX +- add configure branch for SCO and HPUX +- avoid many warnings (unused variables, dead assignments, etc...) +- no fdopen for BeOS +- fix the Watcom fix for 32 bit mode (define FAR as empty) +- removed redefinition of Byte for MKWERKS +- work around an MWKERKS bug (incorrect merge of all .h files) + +Changes in 0.99 (27 Jan 96) +- allow preset dictionary shared between compressor and decompressor +- allow compression level 0 (no compression) +- add deflateParams in zlib.h: allow dynamic change of compression level + and compression strategy +- test large buffers and deflateParams in example.c +- add optional "configure" to build zlib as a shared library +- suppress Makefile.qnx, use configure instead +- fixed deflate for 64-bit systems (detected on Cray) +- fixed inflate_blocks for 64-bit systems (detected on Alpha) +- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2) +- always return Z_BUF_ERROR when deflate() has nothing to do +- deflateInit and inflateInit are now macros to allow version checking +- prefix all global functions and types with z_ with -DZ_PREFIX +- make falloc completely reentrant (inftrees.c) +- fixed very unlikely race condition in ct_static_init +- free in reverse order of allocation to help memory manager +- use zlib-1.0/* instead of zlib/* inside the tar.gz +- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith + -Wconversion -Wstrict-prototypes -Wmissing-prototypes" +- allow gzread on concatenated .gz files +- deflateEnd now returns Z_DATA_ERROR if it was premature +- deflate is finally (?) fully deterministic (no matches beyond end of input) +- Document Z_SYNC_FLUSH +- add uninstall in Makefile +- Check for __cpluplus in zlib.h +- Better test in ct_align for partial flush +- avoid harmless warnings for Borland C++ +- initialize hash_head in deflate.c +- avoid warning on fdopen (gzio.c) for HP cc -Aa +- include stdlib.h for STDC compilers +- include errno.h for Cray +- ignore error if ranlib doesn't exist +- call ranlib twice for NeXTSTEP +- use exec_prefix instead of prefix for libz.a +- renamed ct_* as _tr_* to avoid conflict with applications +- clear z->msg in inflateInit2 before any error return +- initialize opaque in example.c, gzio.c, deflate.c and inflate.c +- fixed typo in zconf.h (_GNUC__ => __GNUC__) +- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode) +- fix typo in Make_vms.com (f$trnlnm -> f$getsyi) +- in fcalloc, normalize pointer if size > 65520 bytes +- don't use special fcalloc for 32 bit Borland C++ +- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc. +- use Z_BINARY instead of BINARY +- document that gzclose after gzdopen will close the file +- allow "a" as mode in gzopen +- fix error checking in gzread +- allow skipping .gz extra-field on pipes +- added reference to Perl interface in README +- put the crc table in FAR data (I dislike more and more the medium model :) +- added get_crc_table +- added a dimension to all arrays (Borland C can't count) +- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast +- guard against multiple inclusion of *.h (for precompiled header on Mac) +- Watcom C pretends to be Microsoft C small model even in 32 bit mode +- don't use unsized arrays to avoid silly warnings by Visual C++: + warning C4746: 'inflate_mask' : unsized array treated as '__far' + (what's wrong with far data in far model?) +- define enum out of inflate_blocks_state to allow compilation with C++ + +Changes in 0.95 (16 Aug 95) +- fix MSDOS small and medium model (now easier to adapt to any compiler) +- inlined send_bits +- fix the final (:-) bug for deflate with flush (output was correct but + not completely flushed in rare occasions) +- default window size is same for compression and decompression + (it's now sufficient to set MAX_WBITS in zconf.h) +- voidp -> voidpf and voidnp -> voidp (for consistency with other + typedefs and because voidnp was not near in large model) + +Changes in 0.94 (13 Aug 95) +- support MSDOS medium model +- fix deflate with flush (could sometimes generate bad output) +- fix deflateReset (zlib header was incorrectly suppressed) +- added support for VMS +- allow a compression level in gzopen() +- gzflush now calls fflush +- For deflate with flush, flush even if no more input is provided +- rename libgz.a as libz.a +- avoid complex expression in infcodes.c triggering Turbo C bug +- work around a problem with gcc on Alpha (in INSERT_STRING) +- don't use inline functions (problem with some gcc versions) +- allow renaming of Byte, uInt, etc... with #define +- avoid warning about (unused) pointer before start of array in deflate.c +- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c +- avoid reserved word 'new' in trees.c + +Changes in 0.93 (25 June 95) +- temporarily disable inline functions +- make deflate deterministic +- give enough lookahead for PARTIAL_FLUSH +- Set binary mode for stdin/stdout in minigzip.c for OS/2 +- don't even use signed char in inflate (not portable enough) +- fix inflate memory leak for segmented architectures + +Changes in 0.92 (3 May 95) +- don't assume that char is signed (problem on SGI) +- Clear bit buffer when starting a stored block +- no memcpy on Pyramid +- suppressed inftest.c +- optimized fill_window, put longest_match inline for gcc +- optimized inflate on stored blocks +- untabify all sources to simplify patches + +Changes in 0.91 (2 May 95) +- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h +- Document the memory requirements in zconf.h +- added "make install" +- fix sync search logic in inflateSync +- deflate(Z_FULL_FLUSH) now works even if output buffer too short +- after inflateSync, don't scare people with just "lo world" +- added support for DJGPP + +Changes in 0.9 (1 May 95) +- don't assume that zalloc clears the allocated memory (the TurboC bug + was Mark's bug after all :) +- let again gzread copy uncompressed data unchanged (was working in 0.71) +- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented +- added a test of inflateSync in example.c +- moved MAX_WBITS to zconf.h because users might want to change that +- document explicitly that zalloc(64K) on MSDOS must return a normalized + pointer (zero offset) +- added Makefiles for Microsoft C, Turbo C, Borland C++ +- faster crc32() + +Changes in 0.8 (29 April 95) +- added fast inflate (inffast.c) +- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this + is incompatible with previous versions of zlib which returned Z_OK +- work around a TurboC compiler bug (bad code for b << 0, see infutil.h) + (actually that was not a compiler bug, see 0.81 above) +- gzread no longer reads one extra byte in certain cases +- In gzio destroy(), don't reference a freed structure +- avoid many warnings for MSDOS +- avoid the ERROR symbol which is used by MS Windows + +Changes in 0.71 (14 April 95) +- Fixed more MSDOS compilation problems :( There is still a bug with + TurboC large model + +Changes in 0.7 (14 April 95) +- Added full inflate support +- Simplified the crc32() interface. The pre- and post-conditioning + (one's complement) is now done inside crc32(). WARNING: this is + incompatible with previous versions; see zlib.h for the new usage + +Changes in 0.61 (12 April 95) +- workaround for a bug in TurboC. example and minigzip now work on MSDOS + +Changes in 0.6 (11 April 95) +- added minigzip.c +- added gzdopen to reopen a file descriptor as gzFile +- added transparent reading of non-gziped files in gzread +- fixed bug in gzread (don't read crc as data) +- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose) +- don't allocate big arrays in the stack (for MSDOS) +- fix some MSDOS compilation problems + +Changes in 0.5: +- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but + not yet Z_FULL_FLUSH +- support decompression but only in a single step (forced Z_FINISH) +- added opaque object for zalloc and zfree +- added deflateReset and inflateReset +- added a variable zlib_version for consistency checking +- renamed the 'filter' parameter of deflateInit2 as 'strategy' + Added Z_FILTERED and Z_HUFFMAN_ONLY constants + +Changes in 0.4: +- avoid "zip" everywhere, use zlib instead of ziplib +- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush + if compression method == 8 +- added adler32 and crc32 +- renamed deflateOptions as deflateInit2, call one or the other but not both +- added the method parameter for deflateInit2 +- added inflateInit2 +- simplified considerably deflateInit and inflateInit by not supporting + user-provided history buffer. This is supported only in deflateInit2 + and inflateInit2 + +Changes in 0.3: +- prefix all macro names with Z_ +- use Z_FINISH instead of deflateEnd to finish compression +- added Z_HUFFMAN_ONLY +- added gzerror() diff --git a/vendor/tcl/compat/zlib/FAQ b/vendor/tcl/compat/zlib/FAQ new file mode 100644 index 00000000..95c1a825 --- /dev/null +++ b/vendor/tcl/compat/zlib/FAQ @@ -0,0 +1,371 @@ + + Frequently Asked Questions about zlib + + +If your question is not there, please check the zlib home page +https://zlib.net/ which may have more recent information. +The latest zlib FAQ is at https://zlib.net/zlib_faq.html + + + 1. Is zlib Y2K-compliant? + + Yes. zlib doesn't handle dates. + + 2. Where can I get a Windows DLL version? + + The zlib sources can be compiled without change to produce a DLL. See the + file win32/DLL_FAQ.txt in the zlib distribution. + + 3. Where can I get a Visual Basic interface to zlib? + + See + * https://zlib.net/nelson/ + * win32/DLL_FAQ.txt in the zlib distribution + + 4. compress() returns Z_BUF_ERROR. + + Make sure that before the call of compress(), the length of the compressed + buffer is equal to the available size of the compressed buffer and not + zero. For Visual Basic, check that this parameter is passed by reference + ("as any"), not by value ("as long"). + + 5. deflate() or inflate() returns Z_BUF_ERROR. + + Before making the call, make sure that avail_in and avail_out are not zero. + When setting the parameter flush equal to Z_FINISH, also make sure that + avail_out is big enough to allow processing all pending input. Note that a + Z_BUF_ERROR is not fatal--another call to deflate() or inflate() can be + made with more input or output space. A Z_BUF_ERROR may in fact be + unavoidable depending on how the functions are used, since it is not + possible to tell whether or not there is more output pending when + strm.avail_out returns with zero. See https://zlib.net/zlib_how.html for a + heavily annotated example. + + 6. Where's the zlib documentation (man pages, etc.)? + + It's in zlib.h . Examples of zlib usage are in the files test/example.c + and test/minigzip.c, with more in examples/ . + + 7. Why don't you use GNU autoconf or libtool or ...? + + Because we would like to keep zlib as a very small and simple package. + zlib is rather portable and doesn't need much configuration. + + 8. I found a bug in zlib. + + Most of the time, such problems are due to an incorrect usage of zlib. + Please try to reproduce the problem with a small program and send the + corresponding source to us at zlib@gzip.org . Do not send multi-megabyte + data files without prior agreement. + + 9. Why do I get "undefined reference to gzputc"? + + If "make test" produces something like + + example.o(.text+0x154): undefined reference to `gzputc' + + check that you don't have old files libz.* in /usr/lib, /usr/local/lib or + /usr/X11R6/lib. Remove any old versions, then do "make install". + +10. I need a Delphi interface to zlib. + + See the contrib/delphi directory in the zlib distribution. + +11. Can zlib handle .zip archives? + + Not by itself, no. See the directory contrib/minizip in the zlib + distribution. + +12. Can zlib handle .Z files? + + No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt + the code of uncompress on your own. + +13. How can I make a Unix shared library? + + By default a shared (and a static) library is built for Unix. So: + + make distclean + ./configure + make + +14. How do I install a shared zlib library on Unix? + + After the above, then: + + make install + + However, many flavors of Unix come with a shared zlib already installed. + Before going to the trouble of compiling a shared version of zlib and + trying to install it, you may want to check if it's already there! If you + can #include , it's there. The -lz option will probably link to + it. You can check the version at the top of zlib.h or with the + ZLIB_VERSION symbol defined in zlib.h . + +15. I have a question about OttoPDF. + + We are not the authors of OttoPDF. The real author is on the OttoPDF web + site: Joel Hainley, jhainley@myndkryme.com. + +16. Can zlib decode Flate data in an Adobe PDF file? + + Yes. See https://www.pdflib.com/ . To modify PDF forms, see + https://sourceforge.net/projects/acroformtool/ . + +17. Why am I getting this "register_frame_info not found" error on Solaris? + + After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib + generates an error such as: + + ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so: + symbol __register_frame_info: referenced symbol not found + + The symbol __register_frame_info is not part of zlib, it is generated by + the C compiler (cc or gcc). You must recompile applications using zlib + which have this problem. This problem is specific to Solaris. See + http://www.sunfreeware.com for Solaris versions of zlib and applications + using zlib. + +18. Why does gzip give an error on a file I make with compress/deflate? + + The compress and deflate functions produce data in the zlib format, which + is different and incompatible with the gzip format. The gz* functions in + zlib on the other hand use the gzip format. Both the zlib and gzip formats + use the same compressed data format internally, but have different headers + and trailers around the compressed data. + +19. Ok, so why are there two different formats? + + The gzip format was designed to retain the directory information about a + single file, such as the name and last modification date. The zlib format + on the other hand was designed for in-memory and communication channel + applications, and has a much more compact header and trailer and uses a + faster integrity check than gzip. + +20. Well that's nice, but how do I make a gzip file in memory? + + You can request that deflate write the gzip format instead of the zlib + format using deflateInit2(). You can also request that inflate decode the + gzip format using inflateInit2(). Read zlib.h for more details. + +21. Is zlib thread-safe? + + Yes. However any library routines that zlib uses and any application- + provided memory allocation routines must also be thread-safe. zlib's gz* + functions use stdio library routines, and most of zlib's functions use the + library memory allocation routines by default. zlib's *Init* functions + allow for the application to provide custom memory allocation routines. + + If the non-default BUILDFIXED or DYNAMIC_CRC_TABLE defines are used on a + system without atomics (e.g. pre-C11), then inflate() and crc32() will not + be thread safe. + + Of course, you should only operate on any given zlib or gzip stream from a + single thread at a time. + +22. Can I use zlib in my commercial application? + + Yes. Please read the license in zlib.h. + +23. Is zlib under the GNU license? + + No. Please read the license in zlib.h. + +24. The license says that altered source versions must be "plainly marked". So + what exactly do I need to do to meet that requirement? + + You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In + particular, the final version number needs to be changed to "f", and an + identification string should be appended to ZLIB_VERSION. Version numbers + x.x.x.f are reserved for modifications to zlib by others than the zlib + maintainers. For example, if the version of the base zlib you are altering + is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and + ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also + update the version strings in deflate.c and inftrees.c. + + For altered source distributions, you should also note the origin and + nature of the changes in zlib.h, as well as in ChangeLog and README, along + with the dates of the alterations. The origin should include at least your + name (or your company's name), and an email address to contact for help or + issues with the library. + + Note that distributing a compiled zlib library along with zlib.h and + zconf.h is also a source distribution, and so you should change + ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes + in zlib.h as you would for a full source distribution. + +25. Will zlib work on a big-endian or little-endian architecture, and can I + exchange compressed data between them? + + Yes and yes. + +26. Will zlib work on a 64-bit machine? + + Yes. It has been tested on 64-bit machines, and has no dependence on any + data types being limited to 32-bits in length. If you have any + difficulties, please provide a complete problem report to zlib@gzip.org + +27. Will zlib decompress data from the PKWare Data Compression Library? + + No. The PKWare DCL uses a completely different compressed data format than + does PKZIP and zlib. However, you can look in zlib's contrib/blast + directory for a possible solution to your problem. + +28. Can I access data randomly in a compressed stream? + + No, not without some preparation. If when compressing you periodically use + Z_FULL_FLUSH, carefully write all the pending data at those points, and + keep an index of those locations, then you can start decompression at those + points. You have to be careful to not use Z_FULL_FLUSH too often, since it + can significantly degrade compression. Alternatively, you can scan a + deflate stream once to generate an index, and then use that index for + random access. See examples/zran.c . + +29. Does zlib work on MVS, OS/390, CICS, etc.? + + It has in the past, but we have not heard of any recent evidence. There + were working ports of zlib 1.1.4 to MVS, but those links no longer work. + If you know of recent, successful applications of zlib on these operating + systems, please let us know. Thanks. + +30. Is there some simpler, easier to read version of inflate I can look at to + understand the deflate format? + + First off, you should read RFC 1951. Second, yes. Look in zlib's + contrib/puff directory. + +31. Does zlib infringe on any patents? + + As far as we know, no. In fact, that was originally the whole point behind + zlib. Look here for some more information: + + https://web.archive.org/web/20180729212847/http://www.gzip.org/#faq11 + +32. Can zlib work with greater than 4 GB of data? + + Yes. inflate() and deflate() will process any amount of data correctly. + Each call of inflate() or deflate() is limited to input and output chunks + of the maximum value that can be stored in the compiler's "unsigned int" + type, but there is no limit to the number of chunks. Note however that the + strm.total_in and strm_total_out counters may be limited to 4 GB. These + counters are provided as a convenience and are not used internally by + inflate() or deflate(). The application can easily set up its own counters + updated after each call of inflate() or deflate() to count beyond 4 GB. + compress() and uncompress() may be limited to 4 GB, since they operate in a + single call. gzseek() and gztell() may be limited to 4 GB depending on how + zlib is compiled. See the zlibCompileFlags() function in zlib.h. + + The word "may" appears several times above since there is a 4 GB limit only + if the compiler's "long" type is 32 bits. If the compiler's "long" type is + 64 bits, then the limit is 16 exabytes. + +33. Does zlib have any security vulnerabilities? + + The only one that we are aware of is potentially in gzprintf(). If zlib is + compiled to use sprintf() or vsprintf(), which requires that ZLIB_INSECURE + be defined, then there is no protection against a buffer overflow of an 8K + string space (or other value as set by gzbuffer()), other than the caller + of gzprintf() assuring that the output will not exceed 8K. On the other + hand, if zlib is compiled to use snprintf() or vsnprintf(), which should + normally be the case, then there is no vulnerability. The ./configure + script will display warnings if an insecure variation of sprintf() will be + used by gzprintf(). Also the zlibCompileFlags() function will return + information on what variant of sprintf() is used by gzprintf(). + + If you don't have snprintf() or vsnprintf() and would like one, you can + find a good portable implementation in stb_sprintf.h here: + + https://github.com/nothings/stb + + Note that you should be using the most recent version of zlib. Versions + 1.1.3 and before were subject to a double-free vulnerability, and versions + 1.2.1 and 1.2.2 were subject to an access exception when decompressing + invalid compressed data. + +34. Is there a Java version of zlib? + + Probably what you want is to use zlib in Java. zlib is already included + as part of the Java SDK in the java.util.zip package. If you really want + a version of zlib written in the Java language, look on the zlib home + page for links: https://zlib.net/ . + +35. I get this or that compiler or source-code scanner warning when I crank it + up to maximally-pedantic. Can't you guys write proper code? + + Many years ago, we gave up attempting to avoid warnings on every compiler + in the universe. It just got to be a waste of time, and some compilers + were downright silly as well as contradicted each other. So now, we simply + make sure that the code always works. + +36. Valgrind (or some similar memory access checker) says that deflate is + performing a conditional jump that depends on an uninitialized value. + Isn't that a bug? + + No. That is intentional for performance reasons, and the output of deflate + is not affected. This only started showing up recently since zlib 1.2.x + uses malloc() by default for allocations, whereas earlier versions used + calloc(), which zeros out the allocated memory. Even though the code was + correct, versions 1.2.4 and later was changed to not stimulate these + checkers. + +37. Will zlib read the (insert any ancient or arcane format here) compressed + data format? + + Probably not. Look in the comp.compression FAQ for pointers to various + formats and associated software. + +38. How can I encrypt/decrypt zip files with zlib? + + zlib doesn't support encryption. The original PKZIP encryption is very + weak and can be broken with freely available programs. To get strong + encryption, use GnuPG, https://www.gnupg.org/ , which already includes zlib + compression. For PKZIP compatible "encryption", look at + https://infozip.sourceforge.net/ + +39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings? + + "gzip" is the gzip format, and "deflate" is the zlib format. They should + probably have called the second one "zlib" instead to avoid confusion with + the raw deflate compressed data format. While the HTTP 1.1 RFC 2616 + correctly points to the zlib specification in RFC 1950 for the "deflate" + transfer encoding, there have been reports of servers and browsers that + incorrectly produce or expect raw deflate data per the deflate + specification in RFC 1951, most notably Microsoft. So even though the + "deflate" transfer encoding using the zlib format would be the more + efficient approach (and in fact exactly what the zlib format was designed + for), using the "gzip" transfer encoding is probably more reliable due to + an unfortunate choice of name on the part of the HTTP 1.1 authors. + + Bottom line: use the gzip format for HTTP 1.1 encoding. + +40. Does zlib support the new "Deflate64" format introduced by PKWare? + + No. PKWare has apparently decided to keep that format proprietary, since + they have not documented it as they have previous compression formats. In + any case, the compression improvements are so modest compared to other more + modern approaches, that it's not worth the effort to implement. + +41. I'm having a problem with the zip functions in zlib, can you help? + + There are no zip functions in zlib. You are probably using minizip by + Giles Vollant, which is found in the contrib directory of zlib. It is not + part of zlib. In fact none of the stuff in contrib is part of zlib. The + files in there are not supported by the zlib authors. You need to contact + the authors of the respective contribution for help. + +42. The match.asm code in contrib is under the GNU General Public License. + Since it's part of zlib, doesn't that mean that all of zlib falls under the + GNU GPL? + + No. The files in contrib are not part of zlib. They were contributed by + other authors and are provided as a convenience to the user within the zlib + distribution. Each item in contrib has its own license. + +43. Is zlib subject to export controls? What is its ECCN? + + zlib is not subject to export controls, and so is classified as EAR99. + +44. Can you please sign these lengthy legal documents and fax them back to us + so that we can use your software in our product? + + No. Go away. Shoo. diff --git a/vendor/tcl/compat/zlib/INDEX b/vendor/tcl/compat/zlib/INDEX new file mode 100644 index 00000000..ea022d62 --- /dev/null +++ b/vendor/tcl/compat/zlib/INDEX @@ -0,0 +1,67 @@ +CMakeLists.txt cmake build file +ChangeLog history of changes +FAQ Frequently Asked Questions about zlib +INDEX this file +Makefile dummy Makefile that tells you to ./configure +Makefile.in template for Unix Makefile +README guess what +configure configure script for Unix +make_vms.com makefile for VMS +test/example.c zlib usages examples for build testing +test/minigzip.c minimal gzip-like functionality for build testing +test/infcover.c inf*.c code coverage for build coverage testing +treebuild.xml XML description of source file dependencies +zconf.h.cmakein zconf.h template for cmake +zconf.h.in zconf.h template for configure +zlib.3 Man page for zlib +zlib.3.pdf Man page in PDF format +zlib.map Linux symbol information +zlib.pc.in Template for pkg-config descriptor +zlib.pc.cmakein zlib.pc template for cmake +zlib2ansi perl script to convert source files for C++ compilation + +amiga/ makefiles for Amiga SAS C +doc/ documentation for formats and algorithms +msdos/ makefiles for MSDOS +old/ makefiles for various architectures and zlib documentation + files that have not yet been updated for zlib 1.2.x +os400/ makefiles for OS/400 +qnx/ makefiles for QNX +watcom/ makefiles for OpenWatcom +win32/ makefiles for Windows + + zlib public header files (required for library use): +zconf.h +zlib.h + + private source files used to build the zlib library: +adler32.c +compress.c +crc32.c +crc32.h +deflate.c +deflate.h +gzclose.c +gzguts.h +gzlib.c +gzread.c +gzwrite.c +infback.c +inffast.c +inffast.h +inffixed.h +inflate.c +inflate.h +inftrees.c +inftrees.h +trees.c +trees.h +uncompr.c +zutil.c +zutil.h + + source files for sample programs +See examples/README.examples + + unsupported contributions by third parties +See contrib/README.contrib diff --git a/vendor/tcl/compat/zlib/LICENSE b/vendor/tcl/compat/zlib/LICENSE new file mode 100644 index 00000000..b7a69d05 --- /dev/null +++ b/vendor/tcl/compat/zlib/LICENSE @@ -0,0 +1,22 @@ +Copyright notice: + + (C) 1995-2026 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 + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu diff --git a/vendor/tcl/compat/zlib/MODULE.bazel b/vendor/tcl/compat/zlib/MODULE.bazel new file mode 100644 index 00000000..cb4c13ef --- /dev/null +++ b/vendor/tcl/compat/zlib/MODULE.bazel @@ -0,0 +1,9 @@ +module( + name = "zlib", + version = "0.0.0", + compatibility_level = 1, +) + +bazel_dep(name = "platforms", version = "0.0.10") +bazel_dep(name = "rules_cc", version = "0.0.16") +bazel_dep(name = "rules_license", version = "1.0.0") diff --git a/vendor/tcl/compat/zlib/Makefile b/vendor/tcl/compat/zlib/Makefile new file mode 100644 index 00000000..6bba86c7 --- /dev/null +++ b/vendor/tcl/compat/zlib/Makefile @@ -0,0 +1,5 @@ +all: + -@echo "Please use ./configure first. Thank you." + +distclean: + make -f Makefile.in distclean diff --git a/vendor/tcl/compat/zlib/Makefile.in b/vendor/tcl/compat/zlib/Makefile.in new file mode 100644 index 00000000..bee83edf --- /dev/null +++ b/vendor/tcl/compat/zlib/Makefile.in @@ -0,0 +1,426 @@ +# Makefile for zlib +# Copyright (C) 1995-2026 Jean-loup Gailly, Mark Adler +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile and test, type: +# ./configure; make test +# Normally configure builds both a static and a shared library. +# If you want to build just a static library, use: ./configure --static + +# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type: +# make install +# To install in $HOME instead of /usr/local, use: +# make install prefix=$HOME + +CC=cc +GCOV=GCOV +LLVM_GCOV_FLAG=LLMV_GCOV_FLAG + +CFLAGS=-O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-g -DZLIB_DEBUG +#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ +# -Wstrict-prototypes -Wmissing-prototypes + +SFLAGS=-O +LDFLAGS= +TEST_LIBS=-L. libz.a +LDSHARED=$(CC) +CPP=$(CC) -E +VGFMAFLAG= + +STATICLIB=libz.a +SHAREDLIB=libz.so +SHAREDLIBV=libz.so.1.3.2 +SHAREDLIBM=libz.so.1 +LIBS=$(STATICLIB) $(SHAREDLIBV) + +AR=ar +ARFLAGS=rc +RANLIB=ranlib +LDCONFIG=ldconfig +LDSHAREDLIBC=-lc +TAR=tar +SHELL=/bin/sh +EXE= + +prefix = /usr/local +exec_prefix = ${prefix} +libdir = ${exec_prefix}/lib +sharedlibdir = ${libdir} +includedir = ${prefix}/include +mandir = ${prefix}/share/man +man3dir = ${mandir}/man3 +pkgconfigdir = ${libdir}/pkgconfig +SRCDIR= +ZINC= +ZINCOUT=-I. + +OBJZ = adler32.o crc32.o deflate.o infback.o inffast.o inflate.o inftrees.o trees.o zutil.o +OBJG = compress.o uncompr.o gzclose.o gzlib.o gzread.o gzwrite.o +OBJC = $(OBJZ) $(OBJG) + +PIC_OBJZ = adler32.lo crc32.lo deflate.lo infback.lo inffast.lo inflate.lo inftrees.lo trees.lo zutil.lo +PIC_OBJG = compress.lo uncompr.lo gzclose.lo gzlib.lo gzread.lo gzwrite.lo +PIC_OBJC = $(PIC_OBJZ) $(PIC_OBJG) + +# to use the asm code: make OBJA=match.o, PIC_OBJA=match.lo +OBJA = +PIC_OBJA = + +OBJS = $(OBJC) $(OBJA) + +PIC_OBJS = $(PIC_OBJC) $(PIC_OBJA) + +all: static shared + +static: example$(EXE) minigzip$(EXE) + +shared: examplesh$(EXE) minigzipsh$(EXE) + +all64: example64$(EXE) minigzip64$(EXE) + +check: test + +test: all teststatic testshared + +teststatic: static + @TMPST=tmpst_$$; \ + if echo hello world | ${QEMU_RUN} ./minigzip | ${QEMU_RUN} ./minigzip -d && ${QEMU_RUN} ./example $$TMPST ; then \ + echo ' *** zlib test OK ***'; \ + else \ + echo ' *** zlib test FAILED ***'; false; \ + fi + @rm -f tmpst_$$ + +testshared: shared + @LD_LIBRARY_PATH=`pwd`:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ + LD_LIBRARYN32_PATH=`pwd`:$(LD_LIBRARYN32_PATH) ; export LD_LIBRARYN32_PATH; \ + DYLD_LIBRARY_PATH=`pwd`:$(DYLD_LIBRARY_PATH) ; export DYLD_LIBRARY_PATH; \ + SHLIB_PATH=`pwd`:$(SHLIB_PATH) ; export SHLIB_PATH; \ + TMPSH=tmpsh_$$; \ + if echo hello world | ${QEMU_RUN} ./minigzipsh | ${QEMU_RUN} ./minigzipsh -d && ${QEMU_RUN} ./examplesh $$TMPSH; then \ + echo ' *** zlib shared test OK ***'; \ + else \ + echo ' *** zlib shared test FAILED ***'; false; \ + fi + @rm -f tmpsh_$$ + +test64: all64 + @TMP64=tmp64_$$; \ + if echo hello world | ${QEMU_RUN} ./minigzip64 | ${QEMU_RUN} ./minigzip64 -d && ${QEMU_RUN} ./example64 $$TMP64; then \ + echo ' *** zlib 64-bit test OK ***'; \ + else \ + echo ' *** zlib 64-bit test FAILED ***'; false; \ + fi + @rm -f tmp64_$$ + +infcover.o: $(SRCDIR)test/infcover.c $(SRCDIR)zlib.h zconf.h $(SRCDIR)inflate.h $(SRCDIR)inftrees.h + $(CC) $(CFLAGS) $(ZINCOUT) -c -coverage -o $@ $(SRCDIR)test/infcover.c + +infcover: infcover.o libz.a + $(CC) $(CFLAGS) -coverage -o $@ infcover.o libz.a + +cover: infcover + rm -f *.gcda + ${QEMU_RUN} ./infcover + ${GCOV} ${LLVM_GCOV_FLAG} inf*.c -o ./infcover.gcda + +libz.a: $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + -@ ($(RANLIB) $@ || true) >/dev/null 2>&1 + +match.o: match.S + $(CPP) match.S > _match.s + $(CC) -c _match.s + mv _match.o match.o + rm -f _match.s + +match.lo: match.S + $(CPP) match.S > _match.s + $(CC) -c -fPIC _match.s + mv _match.o match.lo + rm -f _match.s + +example.o: $(SRCDIR)test/example.c $(SRCDIR)zlib.h zconf.h + $(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/example.c + +minigzip.o: $(SRCDIR)test/minigzip.c $(SRCDIR)zlib.h zconf.h + $(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/minigzip.c + +example64.o: $(SRCDIR)test/example.c $(SRCDIR)zlib.h zconf.h + $(CC) $(CFLAGS) $(ZINCOUT) -D_FILE_OFFSET_BITS=64 -c -o $@ $(SRCDIR)test/example.c + +minigzip64.o: $(SRCDIR)test/minigzip.c $(SRCDIR)zlib.h zconf.h + $(CC) $(CFLAGS) $(ZINCOUT) -D_FILE_OFFSET_BITS=64 -c -o $@ $(SRCDIR)test/minigzip.c + + +adler32.o: $(SRCDIR)adler32.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)adler32.c + +crc32.o: $(SRCDIR)crc32.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)crc32.c + +crc32_vx.o: $(SRCDIR)contrib/crc32vx/crc32_vx.c + $(CC) $(CFLAGS) $(VGFMAFLAG) $(ZINC) -c -o $@ $(SRCDIR)contrib/crc32vx/crc32_vx.c + +deflate.o: $(SRCDIR)deflate.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)deflate.c + +infback.o: $(SRCDIR)infback.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)infback.c + +inffast.o: $(SRCDIR)inffast.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)inffast.c + +inflate.o: $(SRCDIR)inflate.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)inflate.c + +inftrees.o: $(SRCDIR)inftrees.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)inftrees.c + +trees.o: $(SRCDIR)trees.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)trees.c + +zutil.o: $(SRCDIR)zutil.c $(SRCDIR)gzguts.h + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)zutil.c + +compress.o: $(SRCDIR)compress.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)compress.c + +uncompr.o: $(SRCDIR)uncompr.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)uncompr.c + +gzclose.o: $(SRCDIR)gzclose.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzclose.c + +gzlib.o: $(SRCDIR)gzlib.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzlib.c + +gzread.o: $(SRCDIR)gzread.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzread.c + +gzwrite.o: $(SRCDIR)gzwrite.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzwrite.c + + +adler32.lo: $(SRCDIR)adler32.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/adler32.o $(SRCDIR)adler32.c + -@mv objs/adler32.o $@ + +crc32.lo: $(SRCDIR)crc32.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/crc32.o $(SRCDIR)crc32.c + -@mv objs/crc32.o $@ + +crc32_vx.lo: $(SRCDIR)contrib/crc32vx/crc32_vx.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(VGFMAFLAG) $(ZINC) -DPIC -c -o objs/crc32_vx.o $(SRCDIR)contrib/crc32vx/crc32_vx.c + -@mv objs/crc32_vx.o $@ + +deflate.lo: $(SRCDIR)deflate.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/deflate.o $(SRCDIR)deflate.c + -@mv objs/deflate.o $@ + +infback.lo: $(SRCDIR)infback.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/infback.o $(SRCDIR)infback.c + -@mv objs/infback.o $@ + +inffast.lo: $(SRCDIR)inffast.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/inffast.o $(SRCDIR)inffast.c + -@mv objs/inffast.o $@ + +inflate.lo: $(SRCDIR)inflate.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/inflate.o $(SRCDIR)inflate.c + -@mv objs/inflate.o $@ + +inftrees.lo: $(SRCDIR)inftrees.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/inftrees.o $(SRCDIR)inftrees.c + -@mv objs/inftrees.o $@ + +trees.lo: $(SRCDIR)trees.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/trees.o $(SRCDIR)trees.c + -@mv objs/trees.o $@ + +zutil.lo: $(SRCDIR)zutil.c $(SRCDIR)gzguts.h + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/zutil.o $(SRCDIR)zutil.c + -@mv objs/zutil.o $@ + +compress.lo: $(SRCDIR)compress.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/compress.o $(SRCDIR)compress.c + -@mv objs/compress.o $@ + +uncompr.lo: $(SRCDIR)uncompr.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/uncompr.o $(SRCDIR)uncompr.c + -@mv objs/uncompr.o $@ + +gzclose.lo: $(SRCDIR)gzclose.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzclose.o $(SRCDIR)gzclose.c + -@mv objs/gzclose.o $@ + +gzlib.lo: $(SRCDIR)gzlib.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzlib.o $(SRCDIR)gzlib.c + -@mv objs/gzlib.o $@ + +gzread.lo: $(SRCDIR)gzread.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzread.o $(SRCDIR)gzread.c + -@mv objs/gzread.o $@ + +gzwrite.lo: $(SRCDIR)gzwrite.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzwrite.o $(SRCDIR)gzwrite.c + -@mv objs/gzwrite.o $@ + + +placebo $(SHAREDLIBV): $(PIC_OBJS) libz.a $(SRCDIR)zlib.map + $(LDSHARED) $(SFLAGS) -o $@ $(PIC_OBJS) $(LDSHAREDLIBC) $(LDFLAGS) + rm -f $(SHAREDLIB) $(SHAREDLIBM) + ln -s $@ $(SHAREDLIB) + ln -s $@ $(SHAREDLIBM) + -@rmdir objs + +example$(EXE): example.o $(STATICLIB) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ example.o $(TEST_LIBS) + +minigzip$(EXE): minigzip.o $(STATICLIB) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip.o $(TEST_LIBS) + +examplesh$(EXE): example.o $(SHAREDLIBV) + $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) -L. $(SHAREDLIBV) + +minigzipsh$(EXE): minigzip.o $(SHAREDLIBV) + $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) -L. $(SHAREDLIBV) + +example64$(EXE): example64.o $(STATICLIB) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ example64.o $(TEST_LIBS) + +minigzip64$(EXE): minigzip64.o $(STATICLIB) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip64.o $(TEST_LIBS) + +install-libs: $(LIBS) + -@if [ ! -d $(DESTDIR)$(exec_prefix) ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi + -@if [ ! -d $(DESTDIR)$(libdir) ]; then mkdir -p $(DESTDIR)$(libdir); fi + -@if [ ! -d $(DESTDIR)$(sharedlibdir) ]; then mkdir -p $(DESTDIR)$(sharedlibdir); fi + -@if [ ! -d $(DESTDIR)$(man3dir) ]; then mkdir -p $(DESTDIR)$(man3dir); fi + -@if [ ! -d $(DESTDIR)$(pkgconfigdir) ]; then mkdir -p $(DESTDIR)$(pkgconfigdir); fi + rm -f $(DESTDIR)$(libdir)/$(STATICLIB) + cp $(STATICLIB) $(DESTDIR)$(libdir) + chmod 644 $(DESTDIR)$(libdir)/$(STATICLIB) + -@($(RANLIB) $(DESTDIR)$(libdir)/libz.a || true) >/dev/null 2>&1 + -@if test -n "$(SHAREDLIBV)"; then \ + rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV); \ + cp $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir); \ + echo "cp $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)"; \ + chmod 755 $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV); \ + echo "chmod 755 $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV)"; \ + rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM); \ + ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB); \ + ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM); \ + ($(LDCONFIG) || true) >/dev/null 2>&1; \ + fi + rm -f $(DESTDIR)$(man3dir)/zlib.3 + cp $(SRCDIR)zlib.3 $(DESTDIR)$(man3dir) + chmod 644 $(DESTDIR)$(man3dir)/zlib.3 + rm -f $(DESTDIR)$(pkgconfigdir)/zlib.pc + cp zlib.pc $(DESTDIR)$(pkgconfigdir) + chmod 644 $(DESTDIR)$(pkgconfigdir)/zlib.pc +# The ranlib in install is needed on NeXTSTEP which checks file times +# ldconfig is for Linux + +install: install-libs + -@if [ ! -d $(DESTDIR)$(includedir) ]; then mkdir -p $(DESTDIR)$(includedir); fi + rm -f $(DESTDIR)$(includedir)/zlib.h $(DESTDIR)$(includedir)/zconf.h + cp $(SRCDIR)zlib.h zconf.h $(DESTDIR)$(includedir) + chmod 644 $(DESTDIR)$(includedir)/zlib.h $(DESTDIR)$(includedir)/zconf.h + +uninstall: + cd $(DESTDIR)$(includedir) && rm -f zlib.h zconf.h + cd $(DESTDIR)$(libdir) && rm -f libz.a; \ + if test -n "$(SHAREDLIBV)" -a -f $(SHAREDLIBV); then \ + rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM); \ + fi + cd $(DESTDIR)$(man3dir) && rm -f zlib.3 + cd $(DESTDIR)$(pkgconfigdir) && rm -f zlib.pc + +docs: zlib.3.pdf + +zlib.3.pdf: $(SRCDIR)zlib.3 + groff -mandoc -f H -T ps $(SRCDIR)zlib.3 | ps2pdf - $@ + +# zconf.h.cmakein: $(SRCDIR)zconf.h.in +# -@ TEMPFILE=zconfh_$$; \ +# echo "/#define ZCONF_H/ a\\\\\n#cmakedefine Z_PREFIX\\\\\n#cmakedefine Z_HAVE_UNISTD_H\n" >> $$TEMPFILE &&\ +# sed -f $$TEMPFILE $(SRCDIR)zconf.h.in > $@ &&\ +# touch -r $(SRCDIR)zconf.h.in $@ &&\ +# rm $$TEMPFILE +# + +zconf: $(SRCDIR)zconf.h.in + cp -p $(SRCDIR)zconf.h.in zconf.h + +minizip-test: static + cd contrib/minizip && { CC="$(CC)" CFLAGS="$(CFLAGS)" $(MAKE) test ; cd ../.. ; } + +minizip-clean: + cd contrib/minizip && { $(MAKE) clean ; cd ../.. ; } + +mostlyclean: clean +clean: minizip-clean + rm -f *.o *.lo *~ \ + example$(EXE) minigzip$(EXE) examplesh$(EXE) minigzipsh$(EXE) \ + example64$(EXE) minigzip64$(EXE) \ + infcover \ + libz.* foo.gz so_locations \ + _match.s maketree contrib/infback9/*.o + rm -rf objs + rm -f *.gcda *.gcno *.gcov + rm -f contrib/infback9/*.gcda contrib/infback9/*.gcno contrib/infback9/*.gcov + +maintainer-clean: distclean +distclean: clean zconf # zconf.h.cmakein + rm -f Makefile zlib.pc configure.log + -@rm -f .DS_Store + @if [ -f Makefile.in ]; then \ + printf 'all:\n\t-@echo "Please use ./configure first. Thank you."\n' > Makefile ; \ + printf '\ndistclean:\n\tmake -f Makefile.in distclean\n' >> Makefile ; \ + touch -r $(SRCDIR)Makefile.in Makefile ; fi + +tags: + etags $(SRCDIR)*.[ch] + +adler32.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h +zutil.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)gzguts.h +gzclose.o gzlib.o gzread.o gzwrite.o: $(SRCDIR)zlib.h zconf.h $(SRCDIR)gzguts.h +compress.o example.o minigzip.o uncompr.o: $(SRCDIR)zlib.h zconf.h +crc32.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)crc32.h +deflate.o: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h +infback.o inflate.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h $(SRCDIR)inffixed.h +inffast.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h +inftrees.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h +trees.o: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)trees.h +crc32_vx.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)contrib/crc32vx/crc32_vx_hooks.h + +adler32.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h +zutil.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)gzguts.h +gzclose.lo gzlib.lo gzread.lo gzwrite.lo: $(SRCDIR)zlib.h zconf.h $(SRCDIR)gzguts.h +compress.lo example.lo minigzip.lo uncompr.lo: $(SRCDIR)zlib.h zconf.h +crc32.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)crc32.h +deflate.lo: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h +infback.lo inflate.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h $(SRCDIR)inffixed.h +inffast.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h +inftrees.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h +trees.lo: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)trees.h +crc32_vx.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)contrib/crc32vx/crc32_vx_hooks.h \ No newline at end of file diff --git a/vendor/tcl/compat/zlib/README b/vendor/tcl/compat/zlib/README new file mode 100644 index 00000000..2b1e6f36 --- /dev/null +++ b/vendor/tcl/compat/zlib/README @@ -0,0 +1,115 @@ +ZLIB DATA COMPRESSION LIBRARY + +zlib 1.3.2 is a general purpose data compression library. All the code is +thread safe (though see the FAQ for caveats). The data format used by the zlib +library is described by RFCs (Request for Comments) 1950 to 1952 at +https://datatracker.ietf.org/doc/html/rfc1950 (zlib format), rfc1951 (deflate +format) and rfc1952 (gzip format). + +All functions of the compression library are documented in the file zlib.h +(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example +of the library is given in the file test/example.c which also tests that +the library is working correctly. Another example is given in the file +test/minigzip.c. The compression library itself is composed of all source +files in the root directory. + +To compile all files and run the test program, follow the instructions given at +the top of Makefile.in. In short "./configure; make test", and if that goes +well, "make install" should work for most flavors of Unix. For Windows, use +one of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use +make_vms.com. + +Questions about zlib should be sent to , or to Gilles Vollant + for the Windows DLL version. The zlib home page is +https://zlib.net/ . Before reporting a problem, please check this site to +verify that you have the latest version of zlib; otherwise get the latest +version and check whether the problem still exists or not. + +PLEASE read the zlib FAQ https://zlib.net/zlib_faq.html before asking for help. + +Mark Nelson wrote an article about zlib for the Jan. 1997 +issue of Dr. Dobb's Journal; a copy of the article is available at +https://zlib.net/nelson/ . + +The changes made in version 1.3.2 are documented in the file ChangeLog. + +Unsupported third party contributions are provided in directory contrib/ . + +zlib is available in Java using the java.util.zip package. Follow the API +Documentation link at: https://docs.oracle.com/search/?q=java.util.zip . + +A Perl interface to zlib and bzip2 written by Paul Marquess +can be found at https://github.com/pmqs/IO-Compress . + +A Python interface to zlib written by A.M. Kuchling is +available in Python 1.5 and later versions, see +https://docs.python.org/3/library/zlib.html . + +zlib is built into tcl: https://wiki.tcl-lang.org/page/zlib . + +An experimental package to read and write files in .zip format, written on top +of zlib by Gilles Vollant , is available in the +contrib/minizip directory of zlib. + + +Notes for some targets: + +- For Windows DLL versions, please see win32/DLL_FAQ.txt + +- For 64-bit Irix, deflate.c must be compiled without any optimization. With + -O, one libpng test fails. The test works in 32 bit mode (with the -n32 + compiler flag). The compiler bug has been reported to SGI. + +- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works + when compiled with cc. + +- On Digital Unix 4.0D (formerly OSF/1) on AlphaServer, the cc option -std1 is + necessary to get gzprintf working correctly. This is done by configure. + +- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with + other compilers. Use "make test" to check your compiler. + +- For PalmOs, see https://palmzlib.sourceforge.net/ + + +Acknowledgments: + + The deflate format used by zlib was defined by Phil Katz. The deflate and + zlib specifications were written by L. Peter Deutsch. Thanks to all the + people who reported problems and suggested various improvements in zlib; they + are too numerous to cite here. + +Copyright notice: + + (C) 1995-2026 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 + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* receiving +lengthy legal documents to sign. The sources are provided for free but without +warranty of any kind. The library has been entirely written by Jean-loup +Gailly and Mark Adler; it does not include third-party code. We make all +contributions to and distributions of this project solely in our personal +capacity, and are not conveying any rights to any intellectual property of +any third parties. + +If you redistribute modified sources, we would appreciate that you include in +the file ChangeLog history information documenting your changes. Please read +the FAQ for more information on the distribution of modified source versions. diff --git a/vendor/tcl/compat/zlib/README-cmake.md b/vendor/tcl/compat/zlib/README-cmake.md new file mode 100644 index 00000000..5f276415 --- /dev/null +++ b/vendor/tcl/compat/zlib/README-cmake.md @@ -0,0 +1,79 @@ +# For building with cmake at least version 3.12 (minizip 3.12) is needed + +In most cases the usual + + cmake -S . -B build -D CMAKE_BUILD_TYPE=Release + +will create everything you need, however if you want something off default you can adjust several options fit your needs. +Every option is list below (excluding the cmake-standard options), they can be set via cmake-gui or on cmdline with + + -D