2017-10-05

Sugar: Lisp-like macro system for Tcl

Sugar


會注意到是因為 Debian/Ubuntu 有這個套件 (套件名叫 tcl-sugar),然後就去 Tcler's wiki 看是不是有資料。沒想到可以用 pure Tcl 實作了一個類似 Lisp 的 macro system。

2017-10-02

Magicsplat Tcl/Tk for Windows, Visual Studio 2017 and Jsonnet

Google Jsonnet 在 v0.9.5 加入一個 Visual Studio 2017 的專案檔,這表示已經成功的移植到 Windows(使用 Visual Studio 2017 編譯)。

我按照以前寫的 extension,改寫之前 win 目錄下的 makefile.vc 等檔案,試看看能不能使用 Visual Studio 2017 來編譯 tcljsonnet。結果出現一個很奇怪的狀況,在最後連結的時候,Visual Studio 2017 會一直抱怨 BAWT-Tcl (使用 MinGW-W64 編譯) 所使用的是舊的格式,我需要重新編譯才能夠正確連結。

經過思考,換成 Magicsplat Tcl/Tk for Windows 來測試(注:我安裝 在 c:\Tcl,而 Magicsplat  使用 Visual Studio 編譯),然後就很順利的編譯了,而且 tcljsonnet 也可以很正確的使用,不會有 C++ exception 模式不相容的問題。

但是這樣也代表,微軟 Windows 平台出現了格式的相容性問題,但是除非是一個環境中會使用 MinGW-W64 與 Visual Studio 2017 的人才會很快就遇到這個問題。

但是如果將 MinGW-W64 與 Visual Studio 2017 因為 binary 格式不相容而視為二個平台,就會出現很大的維護問題,至少對我而言會很吃力。而目前看起來,並沒有一個好的解法,還蠻麻煩的。 更新:我把使用 MinGW-64 編譯的 extension(例如我自己寫的 tcl-lmdb)放到 Magicsplat Tcl/Tk for Windows 的 lib 目錄下,發現可以使用,所以看起來問題沒那麼大。目前我還是以使用 Mingw-W64 為主,只有需要 Visual Studio 的時候才使用 Visual Studio。

2017-09-19

BAWT-Tcl Windows installer

BAWT 提供了 8.6.x 系列的 Windows 安裝程式,並且安裝了一些常用的擴充套件以及 BAWT 作者自己的作品。


如果你使用 MSYS2/MinGW-w64 的組合,然後 Tcl 使用 BAWT-Tcl 安裝 (假設是安裝在 c:/Tcl),在編譯自己的套件時有可能會出現一些小亂流。

這是因為 tclConfig.shtkConfig.sh 在編譯的機器所指向的目錄和目標機器並不相同。也就是 TCL_PREFIX, TCL_EXEC_PREFIX, TCL_BUILD_LIB_SPEC, TCL_LIB_SPEC 等目錄所記錄的資料不是正確的。但是要修改很簡單,只要指向正確的目銾就可以解決問題,下面是一個例子:

# Top-level directory in which Tcl's platform-independent files are
# installed.
TCL_PREFIX='/c/Tcl'


假設要改善的話,應該只能夠從安裝程式著手,也就是使用者設定好安裝目錄以後,按照安裝目錄的位置進行改寫。取巧的做法是編譯機器和目標機器的環境很像,然後目標機器的預設目錄符合預設的設定(還是有可能出問題,因為使用者有可能不是安裝在預設位置,但是機率大幅度降低)。

2017-09-17

regex_rez: Tcl bindings for RE2

regex_rez


可是,我目前只需要基本功能,所以只實作最簡單的 fullmatch, partialmatch, replace 和 globalrelpace。


維基百科:
RE2 (software)


第一個測試程式使用內建的正規表示式:
puts -nonewline "Please input a number: "
flush stdout
gets stdin number
if {$number <= 0 || $number >= 10} {
   puts "The range is 1 - 9."
   exit
}

set max [expr pow(10, $number)]
set result [list]

puts "\nNow get the result:"
puts "==========="
puts "Start"
puts "==========="
puts [time {
set re {1.*1|2.*2|3.*3|4.*4|5.*5|6.*6|7.*7|8.*8|9.*9|0.*0}
for {set i 1} {$i < $max} {incr i} {
    if {[regexp $re $i] != 1} {
        lappend result $i
    }
}
} 1]
puts "\n"
puts [join $result ", "]
puts "\n==========="
puts "End"
puts "==========="

第二個測試程式使用 RE2:

package require regex_rez

puts -nonewline "Please input a number: "
flush stdout
gets stdin number
if {$number <= 0 || $number >= 10} {
   puts "The range is 1 - 9."
   exit
}

set max [expr pow(10, $number)]
set result [list]

puts "\nNow get the result:"
puts "==========="
puts "Start"
puts "==========="
puts [time {
set re [regex::re2 create {1.*1|2.*2|3.*3|4.*4|5.*5|6.*6|7.*7|8.*8|9.*9|0.*0}]
for {set i 1} {$i < $max} {incr i} {
    if {[$re partialmatch $i] != 1} {
        lappend result $i
    }
}
} 1]
puts "\n"
puts [join $result ", "]
$re close
puts "\n==========="
puts "End"
puts "==========="

(* 更新測試程式二,加上 $re close,這樣才會正確 close)

內建從輸入數字一到數字九:
475 microseconds per iteration
1029 microseconds per iteration
6884 microseconds per iteration
36152 microseconds per iteration
315566 microseconds per iteration
3134428 microseconds per iteration
32075931 microseconds per iteration
325211857 microseconds per iteration
2147483648 microseconds per iteration

RE2 從輸入數字一到數字九:
325 microseconds per iteration
649 microseconds per iteration
7262 microseconds per iteration
48204 microseconds per iteration
347111 microseconds per iteration
2727082 microseconds per iteration
21171756 microseconds per iteration
173788033 microseconds per iteration
1628503061 microseconds per iteration


雖然沒有很仔細的比較,在這個測試中如果是百萬級數目或者是以前比對,內建的正規表示式表現都很不錯,但是如果數目到達百萬級或者是以後比對,Tcl 內建的正規表示式速度看起來明顯的比較慢。

很有趣的問題。

2017-09-12

tclmixer - use SDL2/SDL2_mixer

tclmixer


TclMixer 使用 SDL 1.2 和 SDL_Mixer 1.2,我這幾天突然有個神奇的想法,那就是如果切換到 SDL2/SDL2_mixer 不知道會不會很難。

所以我下載了 TEA sample extension 然後將 TclMixer 的 source code 移過來,做了一點點小修改(主要是改版本,改成 2.0.0),然後發現…… SDL 和 SDL2 的 API 差距沒想像中大,因為沒改什麼東西,可是看起來 TclMixer 可以用。

實測 openSUSE 42.3 的結果,雖然可以使用,但是 SDL_mixer 還沒有 mp3 的部份,不過 OGG/Vorbis 是可用的。

MP3 的最後一個軟體專利在今年到期,所以一些原本無法直接使用的 MP3 自由軟體應該會開始逐漸重新進入 Linux 世界。至少在我測試 mpg123 的時候,我發現 openSUSE 在 42.3 將這個軟體放進來了(只是 devel package name 有改變,與 packman 的不同,但是主套件和 shared library package name 看起來是一致的)。

2017-09-09

Tcl/Tk 8.7a1 RELEASED

Tcl/Tk 8.7a1 RELEASED


Tcl/Tk 8.7 alpha 1 釋出,這是第一個測試的 alpha 版本,但是離可以穩定使用應該還有一段距離才對。


This release is a development release, and should only be considered for deployment use after considerable testing.

    * [TIP 458] New notifiers based on epoll() or kqueue()
    * [TIP 166] Extended color notation for alpha channel with [$image get|put]
    * [TIP 442] New options to display text in a progressbar
    * [TIP 463] New option: [regsub -command]
    * [TIP 449] [text] undo/redo return character range
    * [TIP 472] Support "0d" as optional prefix for decimal integers
    * [TIP 459] New introspection: [package files]
    * [TIP 470] Access to the context objects in oo definition commands
         => TclOO 1.2.0
    * [TIP 456] Extended C interface for opening server socket
    * Socket accept callbacks now always eval in the global namespace
         *** POTENTIAL INCOMPATIBILITY ***
    * Undocumented command [tk_getFileType] removed
         *** POTENTIAL INCOMPATIBILITY ***
    * [array names -regexp] now supports backrefs
    * Support for and
    * New Win shell builtins: assoc ftype move
    * Fix crash when command overwrite triggers delete trace that
      deletes enclosing namespace.
    * Fix memory leak in [text] widget operations.
    * [spinbox] now handles reversed -to / -from ordering.
    * Revised port selection for server sockets.
    * Repaired shadowing problem with compatibility fonts.
    * Repaired threaded allocator initialization.
    * http 2.8.12 fixes state 100 continue handling
    * library/msgs/*.msg files converted to true utf-8.
    * Itcl 3 "wrong num args" error messages no longer repaired.

2017-08-26

tDOM 0.9.0

ANNOUNCE: tDOM 0.9.0


tDOM 在很長一段時間的 0.8.3 以後,釋出了一個新版 v0.9.0。這版加入了 JSON 的支援,並且在編譯時開啟 html5 選項(需要連結 Google Gumbo html parser library)的情況下就有 html5 parser 可以用。

tDOM contains:

    *  for convenience expat 2.2.0, the XML parser originated from
       James Clark, although you're able to link tDOM with other
       expat versions or the library provided by the system.
    *  building a DOM tree from XML in one go implemented in C for
       maximum performance and minimum memory usage, and DOM I and II
       methods to work on such a tree using either a OO-like or a
       handle syntax.
    *  a Tcl interface to expat for event-like (SAX-like) XML parsing.
    *  a complete, compliant and fast XPath implementation in C
       following the November 99 W3C recommendation for navigating and
       data extraction.
    *  a fast XSLT implementation in C following the W3C Recommendation
       16 November 1999.
    *  optional DTD validation.
    *  a JSON parser which parses any possible JSON input into a DOM
       tree without losing information.
    *  an efficient and Tcl'ish way to create XML and HTML documents
       and JSON string.
    *  as build option an interface to the gumbo HTML5 parser, which
       also digests almost any other HTML.
    *  an even faster simple XML parser for trusted XML input.
    *  additional convenience methods.

2017-08-21

tcl-rocksdb v0.1.1

tcl-rocksdb


RocksDB 更改了授權,從原本的 BSD+PATENTS 變成 BSD+PATENTS/GPL v2 (dual license) 然後又變成 Apache 2.0/GPL v2 (dual license)。

而會修改授權,是因為 Apache 基金會接到 Apache Cassandra Team 的請求,希望能夠釐清使用 RocksDB 是否會有版權上的疑慮以後,公佈了結果,Facebook BSD+PATENTS license 被列為 category-x,同時提出了下列的建議:
  • No new project, sub-project or codebase, which has not used Facebook BSD+patents licensed jars (or similar), are allowed to use them. In other words, if you haven't been using them, you aren't allowed to start. It is Cat-X.
  • If you have been using it, and have done so in a *release*, you have a temporary exclusion from the Cat-X classification thru August 31, 2017. At that point in time, ANY and ALL usage of these Facebook BSD+patents licensed artifacts are DISALLOWED. You must either find a suitably licensed replacement, or do without. There will be NO exceptions.
  • Any situation not covered by the above is an implicit DISALLOWAL of usage.

所以如果 RocksDB 沒有修改授權,那麼 Apache Cassandra 就無法使用 RocksDB,已經使用的 Apache Flink, Apache Samza 等各個專案也需要開始尋找替代品。而 RocksDB team 在 Apache 基金會公佈結果以後,很快就修改了授權,變成 Apache 2.0/GPL v2 (dual license)。

既然授權的疑慮清除(PATENTS 是很複雜的議題,如果可以,我會儘量避開),所以我實作了 tcl-rocksdb (prototype),實作一些最基本的操作,同時也寫了簡易的 test case 測試。因為其它的部份我不知道怎麼實作成 Tcl extension 比較好,所以目前的 v0.1.1 就是我實作上比較知道怎麼做的部份了。


2017/08/22
加入幾個新的 command,更新版本為 v0.2。

另外,我發現 LevelDB 和 RocksDB 的基本操作長的很像,所以按照目前的資料,也寫了一個 tcl-leveldb

2017-08-10

Tcl/Tk 8.6.7 RELEASED

Tcl / Tk 8.6.7 RELEASED


Tcl/Tk 釋出了新的版本 8.6.7,下面是修正的項目:

Summary of Changes since Tcl/Tk 8.6.6:
------------------------------

This is a patch release, so it primarily includes bug fixes and corrections to erratic behavior.  Highlighted changes are noted below. The changes file at the root of the source tree contains a more complete list.  The Timelines of all changes are online.

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

    * [TIP 473] (TclOO 1.1.0) Let [oo::copy] specify target namespace
    * [TIP 464] Support multimedia keys on Windows
    * Revise Tcl_LinkVar to tolerate some prefixes
         *** POTENTIAL INCOMPATIBILITY ***

    * Allow empty command as [interp alias] target
         *** POTENTIAL INCOMPATIBILITY ***

    * Revise Tcl_UtfToUniChar() handling of invalid UTF-8
         *** POTENTIAL INCOMPATIBILITY ***

    * [clock] and [encoding] are now ensembles
    * Several [clock] subcommands are now compiled to bytecode

    * Fix crashes or hangs in...
      - [socket -async ::1 0] with no host
      - Threaded memory allocator in thread finalization
      - Tcl_ListObjReplace() error when passed NULL interp
      - [binary scan a$n] when $n overflows int
      - [lsort -unique [lrepeat [expr {1<<27 1="" br="">      - Drawing many dashed canvas objects
      - Using Tk after IME restart
      - Warp pointer operations
      - [[text .t] insert 0.0 \na; .t replace 2.0 3.0 b]
      - Resource exhaustion processing corrupt GIF

    * Fix memory leaks in...
      - namespace delete when unset trace revives namespace variable.
      - Deletion of the [history] command
      - http::geturl when keep-alive is denied
      - TclJoinPath on a custom Tcl_Filesystem
      - text BTree operations

    * Update Unicode data to 10.0
         *** POTENTIAL INCOMPATIBILITY ***

    * Merge updates from new libtommath release; purge unused files
         *** POTENTIAL INCOMPATIBILITY ***

    * Update bundled zlib to release 1.2.11

    * Remove legacy support macro panic() - conflicts with system libs
         *** POTENTIAL INCOMPATIBILITY ***

    * Revise Tk font support to avoid type mismatch with recent Xft
    * Repair cmd resolver caching, demonstrated by tests resolver-3.1*
    * Repair zlib stream buffer flushing; zlib-7.8 and PNG writing
    * Prevent Win thread termination during init and teardown
    * Make KeyRelease event handling get _L and _R right
    * Repaint ttk::button when its image changes
    * Wrapped text don't start lines with whitespace
    * Non-native themes properly display tri-state buttons
    * File dialog repairs for -typevariable, -initialdir, -initialfile
    * Avoid unreleasable global grab due to menu keyboard traversal
    * Fix Win regression [event generate .e ]
    * Fix [grid configure -in] to fully clear outdated info
    * Fix ttk::combobox proper style with -postoffset (test combobox-3)
    * OSX: Stop [$text bbox] returning negative width
    * Repair autoloader fragility loading procs that call tailcall
    * Correct parsing in [scan 0x1 %b], [scan 0x1 %o]
    * Fix [string replace] so test stringComp-14.5 passes
    * Invalidate VFS mounts on sytem encoding change
    * Fix [expr {NaN > "Gran"}] to return 1; string comparison
    * Stop frequent Tcl_GetTime() calls creating clock drift
    * Correct functioning of dynamic unexport of methods
    * Fix [file join a //b] and [file join //a b]
    * Compute correct warp cursor position on 2nd display
    * Enable dismissal of ttk::menubutton without hover
    * Tk_BindEvent filter events Tk ignores avoid X11 ring buffer flood
    * Allow [$photo read] to read files beginning with "-"
    * [text] redisplay calculations corrected on OSX
    * Fix drawing of long text lines on Windows
    * Disabled combobox arrow appearance (danckaert)
    * Fix {PNG -alpha} format for 16-bit color
    * Workaround X11 drawing defects in Ubuntu 16.10+
    * Fix calculation of ttk::notebook tab widths and tab user management
    * Scidb race in notebook tab selection
    * Color name parsing set to reject invalid hex color codes (#ABCZ)
    * OSX scrollbar draw position, highlights, & smooth scroll
    * Race condition on Win clipboard cleanup
    * Center image on button
    * Paneconfigure get pane heights right
    * Windows: User switch forced theme reset
    * Updated bundled packages
       - Itcl 4.1.0      (incompatible with Itk 4.0, get Itk 4.1)
       - sqlite3 3.20.0
       - Thread 2.8.1
       - tdbc* 1.0.5
       - http 2.8.11
       - tcltest 2.4.1
       - msgcat 1.6.1

2017-08-05

Apache Tomcat HTTP/2 與 TclCurl

一閈始是設定 Apache Tomcat HTTP/2 的部份(Apache Tomcat 在 8.5 及以後的版本開始支援)。

HTTP/2 需要 Apache Tomcat Native Library 的支援才行, 所以首先是先安裝 Apache Tomcat Native Library。

Tomcat Native Library 需要 libapr1,所以如果是使用 openSUSE,
sudo zypper install libapr1-devel

再來是自己編譯 Tomcat 或者是使用 RPM 安裝

然後,需要創造 OpenSSL Certificate。 可以參考 Howto: Make Your Own Cert With OpenSSL。

如果只是要自己測試使用所以使用 self-signed,在 conf 目錄下使用下列的指令:
openssl genrsa -out ca.key 4096
openssl req -new -x509 -days 1826 -key ca.key -out ca.crt

最後修改 conf 目錄下的 server.xml,開啟 HTTP/2 的支援並且修改如下:

    <Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"
               maxThreads="150" SSLEnabled="true" >
        <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
        <SSLHostConfig>
            <Certificate certificateKeyFile="conf/ca.key"
                         certificateFile="conf/ca.crt" />
        </SSLHostConfig>
    </Connector>

再來重新開啟 Apache Tomcat server,如果 https://localhost:8443 可以瀏覽,就正確的設定好了(* 因為是 self-signed,所以會看到安全性警告)。


TclCurl 在最近的版本有支援 HTTP/2,下面是驗證 Apache Tomcat HTTP/2 (self-signed) 的範例:
package require TclCurl

set curlHandle [curl::init]
$curlHandle configure -url https://localhost:8443 -sslverifyhost 0 \
    -sslverifypeer 0 -bodyvar result
$curlHandle setopt CURLOPT_HTTP_VERSION 2TLS

catch { $curlHandle perform } curlErrorNumber
if { $curlErrorNumber != 0 } {
    puts "error [curl::easystrerror $curlErrorNumber]"
}

# Print result and clean up
puts $result
$curlHandle cleanup

那麼我們怎麼知道真的是使用 HTTP/2 協定呢?這只要檢查 Tomcat logs 目錄下的 log 就可以確定。

Tcl/Tk 8.6.7 Release Candidates

Tcl/Tk 8.6.7 Release Candidates


8.6.7 RC1 source package.

This collection includes release candidates of packages:
Itcl 4.1.0
http 2.8.11
Thread 2.8.1
msgcat 1.6.1
sqlite3 3.20.0
tcltest 2.4.1
tdbc* 1.0.5

2017-08-03

TclCurl and HTTP/2

TclCurl


HTTP/2 預計在 Java 9 加入支援,所以我想預計會開始增加使用率。

目前 BitBucket 上的 TclCurl 已經加上 HTTP/2 的支援,所以如果要測試 HTTP/2,需要使用 TclCurl。根據 Tcler's Wiki 的資料,目前好像也只有 TclCurl 可以使用 (PS. 目前內建的 http 套件只支援到 1.1)。

Debian 方面,7.22.0+hg20160822-1 這個版本就是使用目前 BitBucket 上到最近的 source code。

openSUSE 的部份我檢查了一下,發現還停留在原作者最後一個釋出的版本,所以我把 openSUSE 的檔案拿過來,加上 BitBucket 上的 source code,然後修改 spec 的 URL 到目前的來源,試著 build 一版看會不會有問題。比較有問題的是版本號碼,因為同一個版本會造成問題(也就是我有可能會進行一些調整,只是還不知道怎麼做比較好) (更新:版本設為 7.22.0+hg20160822) (2017/08/06 更新:放上去 openSUSE build service 測試以後,將版本更新為 7.22.0_hg20160822)。

(另外一個問題是 openSUSE 42.x CURL 版本停在 7.37.0,這表示我可能需要升級 CURL)
(升級到 7.54.1,然後 TclCurl 會發生 libssh2_scp_recv2 找不到的問題,這需要升級 libssh2-1 到新的版本,我升到 libssh2-1-1.8.0-56.2.x86_64 以後解決問題)


更新:
Tools for debugging, testing and using HTTP/2
( 所以 CURL 在  7.43.0及以後的版本,使用 nghttp2 這個函式庫來支援 HTTP/2)

cURL 的文件部份:
HTTP/2 with curl

HTTP/2 解釋文件:
http2 explained

另外的文件:
Introduction to HTTP/2
Chapter 12. HTTP/2

2017-08-01

Swapping variables

資料來自於 Tcler's Wiki - Tcl Gems


使用 Tcl 8.5 內建命令 lassign:
lassign [list $b $a] a b

lassign 可以將一個 list unpack 然後設定其它的變數,利用這一點,就可以交換二個變數的值,很有趣的做法。

2017-07-18

tclmonetdb v0.9.7

Homepage


tclmonetdb

About


MonetDB is an open source column-oriented database management system developed at the Centrum Wiskunde & Informatica (CWI) in the Netherlands.

MonetDB excessively uses main memory for processing, but does not require that all data fit in the available physical memory. To handle a dataset that exceeds the available physical memory, MonetDB does not (only) rely on the available swap space, but (also) uses memory-mapped files to exploit disk storage beyond the swap space as virtual memory.

tclmonetdb is a Tcl extension by using MAPI library to connect MonetDB.

一些說明

  1. Add more string to monetdbSuffixes, for Jul2017 version

這是一個 for MonetDB Jul2017 更新的版本。

2017-07-04

TclProDebug

TclProDebug


The TclPro Debugger version 2.0 is an upgrade of of the debugger included in the TclPro product version 1.5 released and open-sourced by Scriptics Corporation.


FlightAware 贊助的案子,將 TclPro 的 debugger 更新到 Tcl 8.5+ 可以使用。


* 要先編譯 lib 目錄下的 tclparser 並且安裝才行

2017-06-28

Tcl/Tk and ActiveMQ

ActiveMQ: Cross Language Clients and Protocols


網頁下面有使用的範例,其中 Tcl/Tk 的部份有二個,一個是支援 STOMP 協定的 tstomp 套件,一個則是利用 Tcl/Java 來呼叫 Java API。因為有簡單的使用範例,所以我想有需要的時候可以用來參考。


* 另外,ActiveMQ 有支援 MQTT,所以 Tcl MQTT client 可以用來測試是否可以執行,或者是使用我包裝 Paho MQTT C Client 的 Tcl extension tcl.mqttc

2017-06-17

執行程式並且取得標準輸出的結果

set var [list ls -l]
catch {exec {*}$var} result

set lines [split $result "\n"]
foreach line $lines {
    if {[string index $line 0] == "d"} {
        puts $line
    }
}

只是用來練習的程式。使用 exec 來執行程式 (ls -l),取得結果以後再來處理。

2017-06-14

Using Nashorn from Java code (TclBlend version)

package require java

java::import javax.script.ScriptEngine
java::import javax.script.ScriptEngineManager
java::import javax.script.ScriptException

set manager [java::new ScriptEngineManager]
set nashorn [$manager getEngineByName "nashorn"]
set value [$nashorn eval "10 + 20"]
puts "Result: [$value toString]"

Nashorn 是使用 Java 寫的 JavaScript runtime,for Java 8 使用。目前支援的規範是 ECMAScript 5.1。

這裡透過 Nashorn 來執行 JavaScript code。我只是使用 TclBlend 執行 sample code 測試看看。

2017-06-13

apply

set twice {{f v} {apply $f [apply $f $v]}}
set f {{v} {return [expr $v + 5]}}

puts [apply $twice $f 10]

這只是在說明,你可以將匿名函數的內容設給一個變數,然後使用 apply 來呼叫。

2017-06-05

tclhttpd-markdown

tclhttpd-markdown


Tcllib 在 1.18 中 提供了 Markdown 套件,可以將 Markdown 格式轉換為 HTML 的工具。為了檢視這個套件目前的情況,所以作了一個簡略的 TclHttpd 支援。如果是 *.md 檔案,就使用 Tcllib Markdown 套件進行轉換,然後傳回 UTF-8 編碼的 HTML。

我想使用其它的 Markdown 轉換工具應該也是可以,只要修改轉換的部份和提供正確的 package require 就可以才對。

2017-06-04

Apache Tomcat, CGI and Tcl

最近使用 Apache Tomcat 在測試一些東西,所以同時也測試一下如何設定 CGI 以執行 Tcl CGI scrpits 的設定。

預設中 CGI 是 disable 的。在 Apache Tomcat 下使用 Tcl 來撰寫 CGI 程式,需要設定 conf/web.xml 與 conf/context.xml。 可以參考 Apache Tomcat 的文件

首先要設定 web.xml,開啟 CGIServlet 的支援,並且設定執行的程式。 如果是修改 conf/web.xml,那效果是全域性的。如果修改 WEB-INF/web.xml,就只侷限在你的 web application。
    <servlet>
        <servlet-name>cgi</servlet-name>
        <servlet-class>org.apache.catalina.servlets.CGIServlet</servlet-class>
        <init-param>
          <param-name>cgiPathPrefix</param-name>
          <param-value>WEB-INF/cgi</param-value>
        </init-param>
        <init-param>
          <param-name>executable</param-name>
          <param-value>/usr/bin/tclsh</param-value>
        </init-param>        
        <load-on-startup>5</load-on-startup>
    </servlet>

與 URL mapping:
    <servlet-mapping>
        <servlet-name>cgi</servlet-name>
        <url-pattern>/cgi-bin/*</url-pattern>
    </servlet-mapping>

再來是 context.xml,設定 Context 的 privileged 屬性為 true(但是要注意,這樣的更改是全域設定):
<Context privileged="true">

在 webapps/ROOT/WEB-INF 目錄中建立一個新的目錄 cgi。 接下來將我們的 Tcl CGI script 放在 cgi 目錄就可以了。舉例來說,如果是 hello.tcl,網址就是:
http://localhost:8080/cgi-bin/hello.tcl

如果不要在根目錄,舉例來說,可以在 webapps 下建立一個目錄 myapp,myapp 目錄下再建立一個目錄 WEB-INF, 然後 WEB-INF 目錄下再建立目錄 cgi。

接下來將我們的 Tcl CGI script 放在 cgi 目錄,如果正確設定就可以執行。舉例來說,如果是 hello.tcl,網址就是:
http://localhost:8080/myapp/cgi-bin/hello.tcl

2017-05-19

Tcl extension and TDBC driver for CrateDB database : cratedb-tcl 0.1

Source code:
cratedb-tcl


如果需要知道 CrateDB 的一些資料:
CrateDB


因為 CrateDB REST API 支援 Parameter Substitution,所以實際上可以用來模擬 prepare/execute 的行為,這個套件為了驗證這個想法而寫的。

也就是實際上是使用 TclCurl 發出 POST request,然後取得結果。而為了模擬,所以我們將步驟分為幾個部份:
  • prepare: 取得 SQL code,只是放在某個變數中
  • param: 使用者設定參數的型別 (TYPE) 與值 (VALUE)
  • 當使用者呼叫 execute,我們將前面二者的資料結合並且設定好 Parameter Substitution 以後,發出 POST request 然後取得結果
而因為模擬了 prepare/execute,所以我們就可以使用 TDBC 中的 ::tdbc::tokenize 分析 SQL 並且進行參數代換的工作,這部份完成以後,就有一個基本可用的 TDBC driver。

但是需要注意的是因為是用模擬的,跟一般資料庫的行為還是有一些差距,當設定  PARAM 時如果沒有為某個欄位指定 TYPE/VALUE,一般會設為 NULL,雖然 TDBC 的部份我有做一些處理,但是還是沒辦法跟一般的資料庫行為完全一樣。

讓我驚嚇的部份是 CrateDB 欄位部份會自動按照變數 欄位的字母大小排序,也就是在 insert 時不指定欄位順序的話,就會出現插入資料到錯誤的欄位。我反覆測試的時候發現的,目前不知道是 CrateDB 的設計還是 bug。

TclCurl DELETE request (using -customrequest)

package require TclCurl

proc httpBlobDelete {url} {
    set curlHandle [curl::init]
    $curlHandle configure -url $url -customrequest DELETE
    catch { $curlHandle perform } curlErrorNumber
    if { $curlErrorNumber != 0 } {
        return -code error [curl::easystrerror $curlErrorNumber]
    }
    
    set responsecode [$curlHandle getinfo responsecode]
    $curlHandle cleanup
    
    if {$responsecode == 204} {
        return -code ok
    } elseif {$responsecode == 404} {
        return -code error "Not Found"
    } else {
            return -code error "ERROR"
    }
}

用來測試 CrateDB REST API 中 BLOB delete 的程式。

如果 TclCurl 要指定 DELETE request,使用 -customrequest 來指定。因為 CrateDB 會回傳 status code 來表示檔案已成功刪除 (204),或者是沒有這個檔案 (404),所以取得 responsecode 以後判斷。大致上是這樣。


更新:
CrateDB 加入 BLOB 資料使用 PUT,下面是測試的程式:
package require TclCurl

proc httpBlobPut {url data} {
    set curlHandle [curl::init]
    $curlHandle configure -url $url -customrequest PUT -postfields $data
    catch { $curlHandle perform } curlErrorNumber
    if { $curlErrorNumber != 0 } {
        return -code error [curl::easystrerror $curlErrorNumber]
    }
    
    set responsecode [$curlHandle getinfo responsecode]
    $curlHandle cleanup
    
    if {$responsecode == 201} {
        return -code ok
    } elseif {$responsecode == 409} {
        return -code error "Conflict"
    } else {
            return -code error "ERROR"
    }
}


使用 GET 讀取內容:
proc httpBlobGet {url} {
    set curlHandle [curl::init]
    $curlHandle configure -url $url -bodyvar html
    catch { $curlHandle perform } curlErrorNumber
    if { $curlErrorNumber != 0 } {
        return -code error [curl::easystrerror $curlErrorNumber]
    }
    
    set responsecode [$curlHandle getinfo responsecode]
    $curlHandle cleanup
    
    if {$responsecode == 200} {
        return -code ok $html
    } elseif {$responsecode == 404} {
        return -code error "Not Found"
    } else {
            return -code error "ERROR"
    }
}

2017-05-16

tclmonetdb v0.9.6

Homepage


tclmonetdb

About


MonetDB is an open source column-oriented database management system developed at the Centrum Wiskunde & Informatica (CWI) in the Netherlands.

MonetDB excessively uses main memory for processing, but does not require that all data fit in the available physical memory. To handle a dataset that exceeds the available physical memory, MonetDB does not (only) rely on the available swap space, but (also) uses memory-mapped files to exploit disk storage beyond the swap space as virtual memory.

tclmonetdb is a Tcl extension by using MAPI library to connect MonetDB.

一些說明

  1. Add more string to monetdbSuffixes

非常小的更新,不過可以改進我自己的使用情況。

在最近我試著自己建立 MoneDB 的 openSUSE RPM(這樣可以簡化我在安裝上的步驟),觀察 RPM spec 與使用 rpm -qpl 列出檔案,MoneDB 是這樣分類的:
MonetDB-client-11.25.21 -
/usr/bin/mclient
/usr/bin/msqldump
/usr/lib64/libmapi.so.8
/usr/lib64/libmapi.so.8.0.1
/usr/share/licenses/MonetDB-client
/usr/share/licenses/MonetDB-client/COPYING
/usr/share/man/man1/mclient.1.gz
/usr/share/man/man1/msqldump.1.gz

MonetDB-client-devel-11.25.21 -
/usr/include/monetdb
/usr/include/monetdb/mapi.h
/usr/lib64/libmapi.so
/usr/lib64/pkgconfig/monetdb-mapi.pc

所以如果我只想要安裝 MonetDB-client-11.25.21,我就需要更新 monetdbSuffixes,讓 tclmonetdb 會去找 libmapi.so.8 並且載入。所以決定做一個小更新來因應這件事。

2017-05-15

tclmonetdb v0.9.5

Homepage


tclmonetdb

About


MonetDB is an open source column-oriented database management system developed at the Centrum Wiskunde & Informatica (CWI) in the Netherlands.

MonetDB excessively uses main memory for processing, but does not require that all data fit in the available physical memory. To handle a dataset that exceeds the available physical memory, MonetDB does not (only) rely on the available swap space, but (also) uses memory-mapped files to exploit disk storage beyond the swap space as virtual memory.

tclmonetdb is a Tcl extension by using MAPI library to connect MonetDB.

一些說明

  1. Add monet_version method

增加 monet_version 取得 MonetDB 目前的版本。使用的方式為查詢 sys.environment 的方式,取得目前 monet_version 的值。這個方式有個缺點,就是需要有存取的權限,如果權限不足,就會回傳空白的結果。

2017-05-14

info library

info library

info library returns the name of the library directory in which standard Tcl scripts are stored.

我忘記我有沒有記錄過這件事,就是 openSUSE 和 Ubuntu 如果你使用 info library 取得資訊,openSUSE (64 位元) 是在 /usr/lib64/tcl/tcl8.6,但是 Debian/Ubuntu 使用不同的方式來組織 32/64 位元目錄,所以會拿到不同的資訊。

如果是純粹 Tcl 所撰寫的套件,openSUSE 也有可能會放在 /usr/share/tcl 這個目錄下面。

2017-05-12

tclcubrid v0.9.5

Source code

tclcubrid

About


CUBRID is an open source SQL-based relational database management system with object extensions developed by Naver Corporation for web applications.

tclcubrid is a Tcl extension by using CUBRID CCI (CCI Client Interface) driver to connect CUBRID. I write this extension to research CUBRID and CCI (CCI Client Interface) driver.

Main changelog

  1. Improve set/multiset/sequence type handle for fetch_row_list/fetch_row_dict method.
    Now tclcubrid will return a Tcl list for set/multiset/sequence type.
    It is an INCOMPATIBILITY change! User maybe need update source code.
  2. Add blob/clob write size check

改進對於 set/multiset/sequence type 的處理。同時加入更多 blob/clob size 的檢查。


更新:
CUBRID 網站怪怪的,我本來想指向正確的文件位址,結果位址一直變動。最後我覺得煩了,我把位址暫時清掉,然後也重置了  tclcubrid 的 git repository。

更新:
早上起來發現網站又回復為原來的樣子,所以我把連結加回去了,希望接下來不會又出現連結失效的問題。

2017-05-03

TclCurl and YQL

我不太確定 YQL 是不是還有在維護,不過這是用來測試 TclCurl Http GET 的程式,送出查詢給 Yahoo Query Language (YQL),然後取得結果。

package require Tcl 8.6
package require TclOO
package require TclCurl

oo::class create CurlYQL {
    variable html_result
    
    constructor {} {
        set html_result ""
    }
    
    destructor {
    }    
    
    method query {query args} {
        variable url
        variable pairs

        set url "https://query.yahooapis.com/v1/public/yql"
        set pairs {}

        lappend pairs "[curl::escape format]=[curl::escape json]"
        lappend pairs "[curl::escape q]=[curl::escape $query]"
        
        foreach {name value} $args {
            lappend pairs "[curl::escape $name]=[curl::escape $value]"
        }
    
        append url ? [join $pairs &]

        set curlHandle [curl::init]
        $curlHandle configure -url $url -bodyvar [namespace current]::html_result
        catch { $curlHandle perform } curlErrorNumber
        if { $curlErrorNumber != 0 } {
            error [curl::easystrerror $curlErrorNumber]
        }

        $curlHandle cleanup
    }
    
    #
    # get the results
    #
    method getResults {} {
        return $html_result
    }
}

所以接下來就是測試。

送出查詢到 Yhaoo Finance (for CSV file) 查詢 SPY, VOO, IVV 的股價,我們拿到結果以後,使用 rl_json 分析結果並且印出來。

package require rl_json

set curlyql [CurlYQL new]
$curlyql query {select * from csv where url='http://download.finance.yahoo.com/d/quotes.csv?s=SPY,VOO,IVV&f=sl1d1t1c1ohgv&e=.csv' and columns='symbol,price,date,time,change,col1,high,low,col2'}
set query_result [$curlyql getResults]

if {[::rl_json::json exists $query_result query]==1} {
    set rows [::rl_json::json get $query_result query results row]

    puts "========================================\n"
    foreach row $rows {        
        puts "symbol: [dict get $row symbol]"
        puts "price: [dict get $row price]"
        puts "date: [dict get $row date]"
        puts "time: [dict get $row time]"
        puts "change: [dict get $row change]"
        puts "col1: [dict get $row col1]"
        puts "high: [dict get $row high]"
        puts "low: [dict get $row low]"
        puts "col2: [dict get $row col2]"
        puts "========================================\n"
    }
}

$curlyql destroy

* 注意:rl_json 新增加的 command json 放在 namespace rl_json 內,不過使用說明上沒有特別明講,所以需要注意一下這件事。

* 更新:
我把資料放到 Github 上了。

2017-04-29

package vcompare

可以看 Wiki 的解釋

Compares the two version numbers given by version1 and version2. Returns -1 if version1 is an earlier version than version2, 0 if they are equal, and 1 if version1 is later than version2.


實際上的用法可以看 tcllib 中 zipfile::decode module。

if {[package vcompare $tcl_patchLevel "8.6"] < 0} {
  # Only needed pre-8.6
  package require Trf                       ; # Wrapper to zlib
  package require zlibtcl                   ; # Zlib usage. No commands, access through Trf
  set ::zipfile::decode::native_zip_functs 0
} else {
  set ::zipfile::decode::native_zip_functs 1
}

也就是如果 >= 8.6,使用內建的 zlib,如果小於就使用 Trf 與 zlibtcl。

接下來我檢查了一下 zipfile::decode module,發現 zipfile::decode module 並沒有修改完全,::zipfile::decode::GetFile 中沒有使用 native_zip_functs 來選擇要使用的 command。下面是修正的 patch。

     deflate {
         go     $fd(fileloc)
         nbytes $fd(csize)
-        return [zip -mode decompress -nowrap 1 -- [getval]]
+        if {$::zipfile::decode::native_zip_functs} {
+          return [zlib inflate [getval]]
+        } else {
+          return [zip -mode decompress -nowrap 1 -- [getval]]
+        }
     }
     default {
         Error "Unable to handle file \"$src\" compressed with method \"$fd(cm)\"" \



我已經在 Tcl Library Source Repository 開了一個 Ticket 來記錄這件事。

2017-04-14

tclmpi v1.0

目前在 Ubuntu 14.04 上測試過。

Ubuntu 14.04 需要安裝 openmpi,指令如下:
sudo apt-get install openmpi-bin libopenmpi-dev


然後從 https://github.com/akohlmey/tclmpi 或者是 http://sites.google.com/site/akohlmey/software/tclmpi 下載 v1.0 source code。

接下來需要修改 Makefile,讓 tcl.h 可以被正確找到。
TCLINCLUDE=-I/usr/include/tcl

修改完 Makefile 以後,執行 make,然後在 /usr/lib 建立 tclmpi1.0 目錄,將 pkgIndex.tcl, tclmpi.tcl 與 _tclmpi.so 三個檔案複製到 /usr/lib/tclmpi1.0,這樣就完成安裝。

再來使用 examples 下的 hello.tcl 來測試,如果有正確輸出,就表示安裝正確。

package require tclmpi 1.0

# initialize TclMPI
::tclmpi::init

set comm tclmpi::comm_world
set size [::tclmpi::comm_size $comm]
set rank [::tclmpi::comm_rank $comm]

puts "hello world, this is rank $rank of $size"

# close out TclMPI
::tclmpi::finalize
exit 0

2017-04-09

TclTLS-rpm-spec

TclTLS-rpm-spec
TclTLS website


參考 openSUSE 網站上的 RPM spec 以後,做一些小修改造出 1.7.11 的 RPM  檔案。看起來是可以使用,但是只有小量的測試而已,我不知道會不會有什麼問題。

然後寫一個 build.tcl 來加速整個流程。

2017-03-03

zookeepertcl

zookeepertcl

Flightaware 最近在 github 增加了 zookeepertcl,Tcl interface to Apache ZooKeeper distributed coordination system。


如果要寫一個 CP 分散式系統,就我聽過的,在一致性上目前有三個方法可以使用,實作正確的 Raft Consensus Algorithm,實作正確的 Paxos Algorithm 以及使用 Apache Zookeeper。

雖然 Apache Zookeeper 是用 Java 寫的,但是其一致性算法已經經過證明而且十分可靠,所以我想有個 Tcl interface 還是不錯的。


更新:
如果你對 Apache ZooKeeper 的測試報告有興趣,可以閱讀 Jepsen: Zookeeper

2017-02-22

tclreadline and .tclshrc

tclreadline

flightaware clone 了一份 tclreadline 的 source code。如果在 Ubuntu 14.04 下編譯,aux 目錄下會缺少東西,需要使用 libtoolize & aclocal & autoconf & automake --add-missing 來更新。

下面只是嘗試設定 tclsh 提示。

if {$tcl_interactive} {
    package require tclreadline 

    proc ::tclreadline::prompt1 {} {
        global env
        if {[catch {set pwd [pwd]} tmp]} {
            set pwd "unable to get pwd"
        }

        if [info exists env(HOME)] {
            regsub $env(HOME) $pwd "~" pwd
        }


        if [info exists env(USER)] {
            set user $env(USER)
        } else {
            set user tclsh
        }

        return "$user@[lindex [split [info hostname] "."] 0]:$pwd% "
    }

    ::tclreadline::Loop
}



更新:
同時也在 openSUSE 上測試 tclreadline,為了可以快速安裝和移除,參考了其它人的做法以後,使用 RPM spec 和 build script 來造 RPM 檔案

2017-02-08

ActiveTcl 8.6.6 Released

ActiveTcl 8.6.6 (Linux) Released
ActiveTcl 8.6.6 Released


一開始放的是 Linux 平台,最近一天放的則是 Windows x86_64 的安裝檔案。看起來跟之前的目錄組織方法不太一樣,而且 Windows 平台經過安裝測試,找不到 Teacup 相關的檔案。

我不太確定這些改變是暫時的還是永久的。

2017-01-20

BaseXClient-Tcl

Source code:
BaseXClient-Tcl


Tcl client for BaseX database.

BaseX 是一個 XML 資料庫,我只是用來做某些簡單的測試。大部份的功能跟官方的 client 都有點像,不過還是有做一些簡化假設,但是整體上功能應該是差不多的(應該啦)。

2017-01-10

print tcl_platform info

使用 parray 列出來 tcl_platform 的資料:

parray tcl_platform

tcl_platform is an associative array whose elements contain information about the platform on which the application is running, such as the name of the operating system, its current release number, and the machine's instruction set.

2017-01-05

tkvlc: A demo to embed libVLC to Tk toolkit widget

Source code:
tkvlc


使用 OpenGL with C and Tcl/Tk 的方法,將 libVLC 內嵌在 Tk frame widget 內播放影片的方法。

我只有在 openSUSE 上測試。用來驗證這個方法的可行性。


更新:
有些說明沒有寫好,我重新推一個上去 Github。

更新:
會在 Windows build fail,更新 source code。

2017/01/09 更新:
使用 libvlc_media_get_duration 讀取影片的長度。如果在 libvlc_media_player_set_media 之後沒有播放前就讀取,讀到的長度會是 0。

解決的方法有二個,一個是 play 以後 stop,再讀取就會是正確值(就是要先做一小段播放的動作)。一個是 set_media 之後呼叫 libvlc_media_parse,在分析以後 meta info 就會被填寫為正確值,那之後取得的資料就會是正確的。

2017/01/09 更新:
增加更多的 command,並且更新 command 的組織方式。
將版本更新為 v0.3。

2017-01-04

OpenGL with C and Tcl/Tk

OpenGL with C and Tcl/Tk


很有趣的是,這篇文章其實指出了一個很有用的用法,就是拿到 HWND/XWindow ID 以後,我們就可以內嵌一些內容到一個 Tk 的 frame 內。

關鍵是 It involves making a frame widget in Tcl, and then passing its HWND to C to initialize the OpenGL rendering context.


而我猜不只是 OpenGL,具有類似方法的函式庫也可以這樣使用。

因為沒有真的實作過,所以還不確定這個技巧的可用性有多高,但是我直覺認為,這個方法可以結合不少外部函式庫來使用。