2026-06-29

Tcl/Tk 9.0.4

Tcl/Tk 釋出了一個 9.0 的維護版本,9.0.4。

Tcl/Tk 9.0.4 的主要改變可以參考 tcl-release-notes-9.0.4.md, tk-release-notes-9.0.4.md

2026-05-13

Tcl/Tk 8.6.18

Tcl/Tk 釋出了 8.6 系列的新版本,8.6.18

這個版本的主要更新內容可以參考 tcltk-release-notes-8.6.18.txt

注意:This is the last release of the 8.6 series unless very severe issues are found. Only Tcl/Tk 9 will be actively developed from now on.

2026-01-24

TclTLS 2.0

TclTLS 釋出了一個十分重要的重大更新版本,v2.0。下面是這次更新的內容:

  • Replaced build system with a new TEA compliant build system for Unix and windows.
  • Restructured repo and fixed missing TCL Config files.
  • Added TCL 9.0 support.
  • OpenSSL 3 compatibility updates.
  • Added more certificate and connection status.
  • Add missing TLS 1.3 functionality, cipher suites, SNI, ALPN, etc.
  • Error handing improvements, more connect status via callbacks.
  • Fixed OpenSSL 3.0 unexpected EOF issue.
  • When -require 1 is used, will auto validate server certificate.
  • Fixed IO test cases.
  • Fixed many open tickets on sourceforge and core.tcl.tk sites.
  • Use of the Windows system certificate store as a source of trusted root certificates on OpenSSL 3.2 and later.
  • Replaced set DH build args and file with auto select.
  • Replaced process of including tls.tcl file in shared library with cross-platform compatible methods.
  • Disable TLS 1 and 1.1 by default.
  • Use -require 1 as default, when certificates are available.

下面則是我的簡單測試程式。

#!/usr/bin/env tclsh
package require http
package require tls

set protocol "http/1.1"
http::register https 443 [list ::tls::socket -autoservername 1 -require 1 -alpn [list [string tolower $protocol]]]

set tok {}
set url {https://duckduckgo.com/}

try {
    set tok [http::geturl $url -method GET -timeout 3000]
    puts "Status: [::http::ncode $tok]"
    puts "Status Text: [http::status $tok]"
    puts "Headers: [http::meta $tok]"
} on error {em} {
    puts "Error: $em"
} finally {
    # cleanup here
    if {[info exists tok]==1} {
        http::cleanup $tok
    }
}

2025-12-04

NaviServer: Database

NaviServer 目前提供了二種資料庫介面, nsdb 與 後來擴充一些功能的 nsdbi。 nsdb 為 NaviServer 的內建模組(只是需要自行設定載入模組),而 nsdbi 需要使用者自己編譯並且加入到 NaviServer。

注意:如果想要使用 OpenACS 並且資料庫使用 PostgreSQL,那麼必須安裝 nsdbpg 模組。 下面使用 PostgreSQL 測試 nsdb 以及 nsdbpg 模組。使用者需要編譯 nsdbpg 模組並且加入到 NaviServer。 如果要自己編譯 nsdbpg 模組,注意其 Makefile 中 NAVISERVER 所設定的位置, 以及 dbpg.h 中 pg_config.h 和 libpq-fe.h 標頭檔的位置(openSUSE 安裝的位置放在 /usr/include/pgsql)。 下面是標示差異點的 patch 檔案。

--- dbpg.h.org    2025-12-03 16:37:40.171256167 +0800
+++ dbpg.h    2025-12-03 16:37:58.707205142 +0800
@@ -25,7 +25,7 @@
  * pg_config.h. However, the PACKAGE_* macros conflict with
  * NaviServer's packaging information, so we drop these.
  */
-#include <pg_config.h>
+#include <pgsql/pg_config.h>
 #undef PACKAGE_VERSION
 #undef PACKAGE_TARNAME
 #undef PACKAGE_STRING
@@ -34,7 +34,7 @@
 #undef PACKAGE_URL
 
 #include <nsdb.h>
-#include <libpq-fe.h>
+#include <pgsql/libpq-fe.h>
 
 /*
  * Forward compatibility, in case a new version of the module is compiled
--- Makefile.org    2025-12-03 16:39:07.524319290 +0800
+++ Makefile    2025-12-03 16:39:23.699037548 +0800
@@ -27,7 +27,7 @@
 # version of this file under either the License or the GPL.
 
 ifndef NAVISERVER
-    NAVISERVER  = /usr/local/ns
+    NAVISERVER  = /var/lib/naviserver
 endif
 
 #

不過除了直接修改,也可以使用設定參數的方式,下面就是編譯與安裝的指令:

make NAVISERVER=/var/lib/naviserver PGLIB=/usr/lib64 PGINCLUDE=/usr/include/pgsql
sudo make NAVISERVER=/var/lib/naviserver install

在安裝完 nsdbpb 以後,接下來修改 nsd-config.tcl,首先加入相關的變數:

# For database
dict set defaultConfig db_name           danilo
dict set defaultConfig db_user           danilo
dict set defaultConfig db_password       danilo
dict set defaultConfig db_host           localhost
dict set defaultConfig db_port           5432

加入 nsdb 模組,讓 NaviServer 在啟動時會載入模組。

ns_section ns/server/default/modules {
    if {$nscpport ne ""} {ns_param nscp nscp}
    ns_param    nslog               nslog    
    ns_param    nscgi               nscgi
    ns_param    nsperm              nsperm
    ns_param    nsdb                nsdb
    ns_param    revproxy            tcl
}

然後加入 nsdbpg driver 的設定。

ns_section ns/db/drivers {
    ns_param postgres nsdbpg
}

接下來加入 connection pool 的設定。使用者可以設定不止一個 pool,我在這裡只是驗證如何設定,所以只加入一個。

ns_section ns/server/default/db {
   #ns_param Pools pool1,pool2
   ns_param Pools pool1
   ns_param defaultpool pool1
}

ns_section ns/db/pools {
    ns_param pool1 "This is pool1 for PostgreSQL"
}

ns_section ns/db/pool/pool1 {
   ns_param Connections        10
   ns_param LogMinDuration     10ms
   ns_param LogSQLerrors       false
   ns_param driver             postgres
   ns_param DataSource         ${db_host}:${db_port}:${db_name}
   ns_param user               $db_user
   ns_param password           $db_password
}

最後寫一個簡單的測試程式測試。

<%
     ns_adp_puts "NaviServer nsdbpg module - get PostgreSQL version<br>"

     set db [ns_db gethandle]
     set result [ns_db 1row $db "select version() as version"]
     ns_adp_puts [ns_set get $result version]
%>

下面嘗試安裝 nsdbi 以及 nsdbipg。

首先是 nsdbi,下面就是編譯與安裝的指令:

make NAVISERVER=/var/lib/naviserver
sudo make NAVISERVER=/var/lib/naviserver install

再來是 nsdbipg,下面就是編譯與安裝的指令:

make NAVISERVER=/var/lib/naviserver PGLIB=/usr/lib64 PGINCLUDE=/usr/include/pgsql
sudo make NAVISERVER=/var/lib/naviserver install

接下來修改 nsd-config.tcl,首先是加入模組(有二種方式,一種是全域的加入方法,一種是 per server 的加入方式, 這裡使用後一種):

ns_section ns/server/default/modules {
    if {$nscpport ne ""} {ns_param nscp nscp}
    ns_param    nslog               nslog
    ns_param    nscgi               nscgi
    ns_param    nsperm              nsperm
    ns_param    revproxy            tcl
    ns_param    nsdbipg1            nsdbipg
}

以及 nsdbipg1 的設定:

ns_section ns/server/default/module/nsdbipg1 {
    ns_param   default        true ;# This is the default pool
    ns_param   handles        10   ;# Max open handles to db.
    ns_param   maxwait        10   ;# Seconds to wait if handle unavailable.
    ns_param   maxidle        0    ;# Handle closed after maxidle seconds if unused.
    ns_param   maxopen        0    ;# Handle closed after maxopen seconds, regardless of use.
    ns_param   maxqueries     0    ;# Handle closed after maxqueries SQL queries.
    ns_param   checkinterval  600  ;# Check for idle handles every 10 minutes.

    ns_param   datasource     "host='localhost' port=5432 user='danilo' password='danilo' dbname='danilo'"
}

最後寫一個簡單的測試程式測試。

<%
     ns_adp_puts "NaviServer nsdbipg module - get PostgreSQL version<br>"

     dbi_1row -array result {select version() as version}
     ns_adp_puts $result(version)
%>

如果將取得結果回傳為一個串列:

set result [dbi_rows {select a, b from t}]

foreach {a b} $result {
  lappend lresult [list $a $b]
}

nsdbi 使用 dbi_dml 執行 insert/update/delete 指令。nsdbi 支援 bind variable,使用 :variable 的形式來代表變數。

dbi_dml {insert into test values (3, 'z')}
dbi_dml {insert into test (a, b, c) values (:a, :b, :c)}
set numRows [dbi_dml {update test set b = 'z' where a = 1}]
dbi_dml {delete from test where a = 3}

要注意的是,database handle 由 NaviServer 所管理,所以你在測試程式並沒有看到開啟 handle 的動作。

另外,如果使用 NaviServer 提供的資料庫介面,建議修改 systemd service 檔案 nsd.service, 以 PostgreSQL 來說,最好加入 postgresql.service 的部份,所以可以改為如下:

[Unit]
Description=NaviServer
#After=network.target
After=network.target postgresql.service
Wants=postgresql.service

NaviServer: CGI and ADPs

NaviServer 本身支援 ASP/PHP 類似的寫法,可以內嵌 Tcl 程式碼到網頁中, 稱為 NaviServer Dynamic Pages (ADPs),其副檔名為 adp,可以參考下列的網頁:
NaviServer ADP Development

主要的語法有以下三種,第一種為使用 script 標籤:

<script language="tcl" runat="server" stream="on">
...
</script>

第二種則是短標籤:

<% ... %>

第三種則是印出變數的短標籤:

<%= ... %>

NaviServer 已經內建 nscgi 模組。檢查 nsd-config.tcl(或者是你使用的設定檔),確定有載入模組:

ns_section ns/server/default/modules {
    if {$nscpport ne ""} {ns_param nscp nscp}
    ns_param    nslog               nslog
    ns_param    nscgi               nscgi
    ns_param    nsperm              nsperm
    ns_param    revproxy            tcl
}

如果想要使用以前使用 Tcl 寫的 CGI 程式、或者是要使用 NaviServer 練習撰寫 CGI 程式, 只要注意 NaviServer cgi-bin 設定的位置正確的放置檔案,以及正確的加入 Tcl interpreter 的設定即可。 接下來修改 nsd-config.tcl:

ns_section ns/server/default/module/nscgi {
    ns_param    map                 "GET  /cgi-bin $home/cgi-bin"
    ns_param    map                 "POST /cgi-bin $home/cgi-bin"
    ns_param    interps              CGIinterps
    #ns_param   allowstaticresources true    ;# default false; serve static resources from cgi directories
}
    
ns_section ns/interps/CGIinterps {
    ns_param    .pl                 "/usr/bin/perl"
    ns_param    .tcl                "/usr/bin/tclsh"
    ns_param    .sh                 "/bin/bash"
}

PHP 目前在網頁伺服器主要有三種執行的方式,使用 CGI,使用 FastCGI 以及內嵌到網頁伺服器裡。 如果使用 PHP 8.x,php cgi 程式 (php-cgi) 在 openSUSE Tumbleweed 的套件為 php8-fastcgi。 如果想透過 NaviServer 使用 CGI 的方式執行 PHP 是可行的,只要修改 nsd-config.tcl 加入 PHP interpreter 的設定:

ns_section ns/interps/CGIinterps {
    ns_param    .pl                 "/usr/bin/perl"
    ns_param    .php                "/usr/bin/php-cgi"
    ns_param    .tcl                "/usr/bin/tclsh"
    ns_param    .sh                 "/bin/bash"
}

然後寫一個測試程式:

<?php

phpinfo();

?>

2025-11-17

Tcl/Tk 9.0.3

Tcl/Tk 釋出了一個 9.0 的維護版本,9.0.3,說明檔案看起來是從 9.0.2 改的(似乎沒有改完全),不過公告看起來是沒問題的。

Tcl/Tk 9.0.3 的主要改變可以參考 tcl-release-notes-9.0.3.md, tk-release-notes-9.0.3.md

2025-10-21

tcljsonnet v0.18

首頁:
tcljsonnet


主要更新:
將 Jsonnet code base 版本升到 v0.21.0 版。Jsonnet 在 v0.21.0 這一版正式整合進 Rapid YAML(使用 single file 的方式),具有分析 YAML 的能力。在 v0.21.0 版之前開發的版本 Jsonnet 就已經開始加入 Rapid YAML,只是還沒有採用 single file 的方式,使用 single file 這個方式對於我來說比較好整合程式碼。

2025-10-19

tcl.mqttc v0.19

tcl.mqttc

這版整合了 paho.mqtt.c-1.3.15 的相關檔案。至於 C23 中 bool 關鍵字的解法,paho.mqtt.c 使用了更簡單的解法,直接將變數名稱改掉,這樣就可以避免掉問題。

2025-07-06

Tcl/Tk 9.0.2

Tcl/Tk 釋出了一個 9.0 的維護版本,9.0.2。

Tcl/Tk 9.0.2 的主要改變可以參考 tcl-release-notes-9.0.2.md, tk-release-notes-9.0.2.md

2025-06-19

tcl.mqttc v0.18

tcl.mqttc 

GCC15 C 編譯器如果沒有使用 -std 選項指定,編譯時使用的標準為 C23,bool 在 C23 成為關鍵字,所以自定義 bool 的做法在 GCC15 會編譯失敗。目前上遊還沒有確定解法,我只是選一個比較簡單的改法先讓程式能夠編譯成功,然後再看上遊會怎麼修改再進行修正。

#if defined __STDC__ && defined __STDC_VERSION__ && __STDC_VERSION__ <= 201710L
 typedef unsigned int bool;
#endif

也就是使用 __STDC_VERSION__ 進行判斷。

2025-06-18

tablelist 7.6

tablelist 釋出了 v7.6, Scrollutil 則釋出了 v2.6 版,這二個套件都是可以同一個作者,可以在作者的網站下載。另外,tablelist 和 Scrollutil 也是 Tklib 的套件,所以也可以下載最新的 Tklib source code 取得這二個套件。

2025-02-04

Valkey database

在更新 thiredis 之後,需要測試 thiredis 的關係,所以需要一個 Redis 協定相容的資料庫,openSUSE 目前採用的是 Valkey,所以筆記一下他的安裝部份。


Valkey is an open-source in-memory storage, used as a distributed, in-memory key–value database, cache and message broker, with optional durability.

在 openSUSE 安裝的指令:

sudo zypper in valkey

而下面是 README.SUSE 的簡要內容。需要使用 root 的權限進行設定。

  1. cp -a /etc/valkey/valkey.default.conf.template /etc/valkey/instancename.conf

    使用 -a 是因為要保留檔案的 permissions 設定,如果沒有使用,也可以使用下列的指令設定:
    chown root:valkey /etc/valkey/sentinel-instancename.conf
    chmod u=rw,g=rw,o= /etc/valkey/sentinel-instancename.conf

  2. change at least pidfile, logfile and dir setting

    pidfile /run/valkey/instancename.pid
    logfile /var/log/valkey/instancename.log
    dir /var/lib/valkey/instancename/

  3. create the database dir:
    install -d -o valkey -g valkey -m 0750 /var/lib/valkey/instancename/

  4. systemctl start valkey@instancename
  5. systemctl enable valkey@instancename
    (optional: 設定開機會啟動 valkey)

  6. To stop/restart all instances at the same time use:
    systemctl restart valkey.target
    systemctl stop valkey.target

如果要查看目前的狀態,使用:

sudo systemctl status valkey@instancename

如果要加入與 Redis 相容方式的密碼驗證,修改 /etc/valkey/includes/valkey.defaults.conf

requirepass YourStrongPasswordHere

相關連結

2024-12-23

Tcl/Tk 9.0.1

Tcl/Tk 釋出了一個 9.0 的維護版本,9.0.1。

Tcl/Tk 9.0.1 的主要改變可以參考 tcl-release-notes-9.0.1.md, tk-release-notes-9.0.1.md

2024-12-15

Tcl/Tk 8.6.16

 Tcl/Tk 釋出了 8.6 系列的新版本,8.6.16

這個版本的主要更新內容可以參考 tcltk-release-notes-8.6.16.txt

下面就是更新的簡述:

   * Regression in [clock] timezones due to revised tzdata format
   * Improper startup if [pwd] contains a file named init.tcl
   * Fix crashes or hangs in...
      - TclOO + coroutine, oo-1.25
      - lifecycle management of the attributes of a menu entry
      - [grid] and [pack] handling of half-dead argument
      - Tk_DeleteErrorHandler()
      - overwrite of thread data by Tk initialization in second interp
   * Prevent negative zlib stream checksums, zlib-15.1
   * Filesystem path efficiency from skipping unnecessary normalization
   * Revised [clock scan] consistent with leap second timestamp validation
   * Updated bundled packages, libraries, standards, data
      - Itcl 4.3.2
      - sqlite3 3.47.2
      - Thread 2.8.11
      - TDBC* 1.1.10
      - tcltest 2.5.9
      - tzdata 2024b, corrected

2024-11-18

fconfigure -encoding binary in Tcl 9

 注意這個變化:

  • Removed the encoding alias binary to iso8859-1

在 Tcl 9 之前的寫法是  -encoding binary。但是在 Tcl 9 之後如果使用 -encoding binary,會出現一個警告,如果要與之前的語義相同,要將 binary 改為 iso8859-1。下面是一個使用的例子:

fconfigure $fd -blocking 1 -encoding iso8859-1 -translation binary

2024-11-13

Tcl 9 always thread-enabled

Tcl 9.0 的其中一個改變,就是移除了 --disable-threads 編譯選項,所以從 9.0.0 開始都會是 thread-enabled。不過也因為如此,如果你使用下列的方式檢查:

expr {[info exists ::tcl_platform(threaded)] && $::tcl_platform(threaded)}

在 Tcl 9 會得到答案為 0,因為 ::tcl_platform(threaded) 在 Tcl 9 中並不存在。

所以我改寫如下:

#
# Check support thread or not
#
proc is_threaded {} {
  # Tcl 9 always thread-enabled
  if {[package vcompare [info patchlevel] "9.0"] < 0} {
    return [expr {[info exists ::tcl_platform(threaded)] && $::tcl_platform(threaded)}]
  } else {
    return 1
  }
}

目前暫時先這樣,如果有更好的寫法我再更改寫法。
2024/11/16 更新寫法,嘗試使用 package vcompare 來比對版本號。

2024-09-27

Tcl/Tk 9.0.0

 Tcl/Tk 釋出了一個新的主要版本,9.0.0。

Tcl/Tk 9.0 的主要改變可以參考官網的網頁,以及 tcl-release-notes-9.0.0.md, tk-release-notes-9.0.0.md

2024-09-20

Tcl/Tk 8.6.15

Tcl/Tk 釋出了 8.6 系列的新版本,8.6.15

這個版本的主要更新內容可以參考 tcltk-release-notes-8.6.15.txt


2024-07-19

tcl-stbimage v1.1

tcl-stbimage


主要是整合來自 AndroWish project 的 source code,以及更新了 stb_image_resize2.h。

有點麻煩的地方是,AndroWish 有加入了 TkPhoto 相關的程式,並且使用動態載入的方式載入 Tk。但是這個套件一開始的目的就是希望能在沒有 Tk 的情況下使用 stb image 方面的功能;所以我目前並沒有整合 TkPhoto 這部份的程式。

2024-07-09

Tklib 0.8

Tklib is like Tcllib, a collection of many small packages providing utilities, except that packages here are expected to depend on Tk. Tklib specializes in utilities for GUI programming.

Standard Tk Library (tklib) 釋出了 v0.8 版。有興趣的可以參考相關的網頁