顯示具有 Tips 標籤的文章。 顯示所有文章
顯示具有 Tips 標籤的文章。 顯示所有文章

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 來比對版本號。

2022-04-17

openSUSE, Tcl and SQLite

最近的 openSUSE build service 在 devel:languages:tcl/tcl 對 Tcl 套件做了修改,移掉了 Tcl source code 中關於 SQLite3 套件的部份,同時建立與 sqlite3-tcl  套件的依賴性(而這個套件來自於 sqlite3)。

我覺得這似乎有彼此依賴的問題(不確定),不過這樣我就必須把  SQLite3 套件也做一個連結到我 openSUSE build service 的計畫中,才能夠解決其它套件的相依性問題(因為現在 Tcl 會對 sqlite3-tcl 套件產生依賴)。

2019-11-17

Tcl: Group the strings to concatenate together

set s "Hello "
set t "Tcl"
set u "!"
puts $s$t$u

也可以先設到某個變數,再印出來:
set s "Hello "
set t "Tcl"
set u "!"
set str $s$t$u

puts $str


感覺還蠻有趣的。

2019-11-13

Twitter feed for news and Tcl

@TclLang - Twitter feed for news about happenings in the Tcl world.


我之前沒注意到,這是 Tclers's wiki 的官方帳號嗎?不是很確定。

2019-06-08

Tclsh and Here document

Here document

之前我只有在 bash 使用過,今天突然間想試看看 tclsh。我發現…… 對,可以使用同樣的手法。下面就是一個測試的例子:
tclsh - << "EOF"
puts "HELLO World"
EOF

再來是另外一個簡單的測試:
tclsh - << "EOF"
puts [expr 99 + 1]
EOF

這樣就可以在命令列執行簡單的 tclsh 命令。

2019-04-16

使用 QEMU 執行 openSUSE/AARCH64 image

因為 tclBlend 我接到一個 issue,在 AARCH64 下編譯失敗,所以需要一個 AARCH64 模擬器來除錯。


首先要安裝 QEMU-ARM:
sudo zypper install qemu-arm

要下載一個 openSUSE AARCH64 image 來進行測試(我使用 unxz 解壓縮)。
wget https://download.opensuse.org/ports/aarch64/factory/images/openSUSE-Tumbleweed-ARM-JeOS-efi.aarch64-Current.raw.xz
unxz openSUSE-Tumbleweed-ARM-JeOS-efi.aarch64-Current.raw.xz

如果使用 efi image,需要有 Unified EFI BIOS 模擬器正確的載入 boot loader 才行(不然無法正確執行)。我從 Linaro 下載一個來使用。
wget https://releases.linaro.org/components/kernel/uefi-linaro/16.02/release/qemu64/QEMU_EFI.img.gz
gzip -d QEMU_EFI.img.gz 

然後就可以這樣執行:
qemu-system-aarch64 -m 2048 -cpu cortex-a57 -smp 2 -M virt -bios QEMU_EFI.img -serial stdio -device virtio-net-device,netdev=hostnet0,id=net0,mac=52:54:00:09:a4:37 -netdev user,id=hostnet0  -drive if=none,format=raw,file=openSUSE-Tumbleweed-ARM-JeOS-efi.aarch64-Current.raw,id=hd0  -device virtio-blk-device,drive=hd0

(使用者帳號為 root,密碼為 linux)

參考文章:
openSUSE:AArch64
Documentation/Platforms/ARM
Linux on AArch64 ARM 64-bit Architecture
Building ARM Servers With UEFI And ACPI


就 ARM 來說,有二種描述 hardware scheme 的方式,一種是 UEFI/ACPI,一種是 Device Tree。Linux kernel 可以編譯為二種都支援。文件中有提到:

ACPI support in drivers and subsystems for ARMv8 should never be mutually exclusive with DT support at compile time.

At boot time the kernel will only use one description method depending on parameters passed from the boot loader (including kernel bootargs).

Regardless of whether DT or ACPI is used, the kernel must always be capableof booting with either scheme (in kernels with both schemes enabled at compile time).

2019-04-10

Difference between 2 dates in XQuery

package require xqilla

xqilla db
set exprs [db prepare {days-from-duration(xs:dateTime('2019-06-14T00:00:00') - current-dateTime())}]
set result [$exprs execute]
set diff 0

while {[$result next]} {
    set diff [$result string_value]
}

puts "The answer is $diff."

$result close
$exprs close
db close

使用 XQuery 的日期函式計算出二個日期間的差距,這裡使用 XQilla 測試。

Difference between 2 dates in SQLite3

package require tdbc::sqlite3

tdbc::sqlite3::connection create db :memory:
set statement [db prepare {SELECT CAST ((JulianDay('2019-06-14') - JulianDay('now')) as Integer) as d}]    

set diff 0
$statement foreach row {
    if {[catch {set diff [dict get $row d]}]} {
        set diff 0
    }
}

puts "The answer is $diff."

$statement close
db close

使用 SQLite3 的日期函式計算出二個日期間的差距,這裡使用 tdbc::sqlite3 測試。

2018-12-06

Tcl: argv

argv

$argv is a global variable provided by tclsh and wish mainline code.


下面就是 Tcler's wiki 的範例(我只有改寫第一行):
#!/usr/bin/env tclsh

if { $::argc > 0 } {
    set i 1
    foreach arg $::argv {
        puts "argument $i is $arg"
        incr i
    }
} else {
    puts "no command line argument passed"
}

2018-10-09

Tcl: Show platform/arch info

這只是簡單的程式練習。

#!/usr/bin/env tclsh

puts "Platform: $tcl_platform(os)"
puts "Arch: $tcl_platform(machine)"


在 Ubuntu 14.04 64bit 上,答案是這樣:
Platform: Linux
Arch: x86_64

2018-09-27

SQLite3 and UUID

uuid


使用 SQLite3 產生一個亂數的值,然後拿到以後進行處理。因為 SQLite 支援 In-Memory Databases,我加上一點處理的 code,所以可以這樣用:
proc uuid {} {
    try {
        package require sqlite3
        
        sqlite3 db1 ":memory:"
        set u [db1 onecolumn {select (hex(randomblob(16)))}]
        db1 close
        
        return [string range $u 0 7]-[string range $u 8 11]-[string range $u 12 15]-[string range $u 16 19]-[string range $u 20 end]        
    } on error {em} {
        error $em
    }
}


這樣就可以使用 SQLite Tcl interface 產生一個 UUID string。

2018-06-13

ttk::setTheme

ttk::setTheme

This function takes a theme name as an argument. It looks to see if the theme has been loaded, and if not, requires the package, and calls ttk to use the theme. While the code actually also sets a variable, that variable is local to the function and thus isn't available.

可以使用這個函式來設定 Ttk 要使用的 theme。


關於相關的 theme 列表,可以查看 List of ttk Themes。Ttk 已經有內建一些 theme 可以使用。

2018-06-07

try and finally

在 comp.lang.tcl 看到這個寫法,所以我寫了一個練習用的程式來學習這件事:
try 是 Tcl 8.6 內建命令,可以在 finally 釋放所使用的資源。

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

http::register https 443 [list ::tls::socket -ssl3 0 -ssl2 0 -tls1 1]

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
    }
}

(更新:拔掉網路線以後測試,我想需要檢查 tok 是否存在)

相關連結:
try ... finally ... (@ Tclers Wiki!)
TIP 329: Try/Catch/Finally syntax

2018-06-03

TDBC-ODBC: Get Data Sources list

TDBC-ODBC 有提供取得目前 data sources 名單的函式 ::tdbc::odbc::datasources。下面的 code 就是取得目前的名單以後,將資料增加到 tablelist 的片段。
# Get data sources list and list
tablelist::tablelist .t -columns {0 "DSN" 0 "Driver"} -stretch all \
    -background white -font {Helvetica -14}
pack .t -fill both -expand 1 -side top
set sources [::tdbc::odbc::datasources]
foreach {dsn driver} $sources {
   .t insert end [list $dsn $driver]
}

這樣就可以取得目前的 ODBC data sources。


其它部份:
unixODBC 可以在 /etc/unixODBC 目錄中設定 odbc.ini 與 odbcinst.ini,或者是在家目錄下設定 .odbc.ini。

::tdbc::odbc::datasources 如果沒有特別設定,會取得 system 和 user 的名單。TDBC-ODBC 可以使用選項 -system 或者是 -user 來取得個別的名單。

2018-05-28

openSUSE Leap 15.0 and OpenAL Soft

升級到 openSUSE Leap 15.0 以後,使用 tclopenal 播放音樂,都會跑出來下面的錯誤訊息:

Cannot connect to server socket err = No such file or directory
Cannot connect to server request channel
jack server is not running or cannot be started



一開始我沒有搞清楚狀況,所以以為是沒有安裝 Jack Audio Server,但是後來我又想,Linux 一般的預設應該是 ALSA/PulseAudio,所以不應該是沒有安裝 Jack Audio Server 的問題。最後才想到,可能是 OpenAL Soft 的設定問題。

OpenAL Soft 是有支援 Jack 的,所以可能是我之前使用的版本不用設定,或者是之前的版本已經有設定好。但是不管如何,這個錯誤訊息在 openSUSE Leap 15.0 跑出來,所以我需要消除掉這個錯誤訊息。

接下來我發現 /etc/openal 目錄下沒有 alsoft.conf 這個檔案。這給了我提示,所以在搜尋以後,找到答案,我需要建立 alsoft.conf 檔案,並且設定如下:
[general]
drivers = -jack,


經過測試,這樣確實可以消除無法連接到 Jack 的錯誤訊息。

2018-05-09

Tcl: identity function

identity function: The identity function accepts one value and simply returns that value.

Tcl 8.6 可以使用下列的方式:
string cat $var

或者是比較短的寫法:
lindex $var


很有趣的事情。

2018-03-19

Get Linux Distribution Name (Tcl exec 版)

在最後嘗試 Bash 的版本。在嘗試以後,寫好了 Bash 版,使用 cat, grep 和 sed 取得結果。
#!/bin/bash

if [ -f '/etc/os-release' ]; then
    cat '/etc/os-release' | grep -w "^NAME" | sed -e 's/NAME=//g'
fi


於是我就想,那我可以使用同樣的方式在 Tcl  嗎?答案是可以。
#!/usr/bin/env tclsh
#
# Execute external program to get result
#

package require Tcl 8.6

set myfunction {{} {
    return [exec cat /etc/os-release | grep -w "^NAME" | sed -e "s/NAME=//g"]
}}

if {[file exists "/etc/os-release"]==1} {
    puts [apply $myfunction]
}

為了增加變化,所以我使用了匿名函式的寫法。

2018-03-15

Tcl double quotes and string map

這只是 string map 的測試。

set doublequotes {"It is double quotes"}
string map [list {"} {\"}] $doublequotes
string map [list {\"} {"}] $doublequotes

進行雙引號的改寫,從 " 改寫為 \",以及改回來,從 \" 改成 "。

2018-03-13

Use uname to get info

在 Unix-like 的系統可以使用 uname 來取得一些系統資料。下面是使用 uname -s 來取得目前的 OS 資訊。

proc getKernelName {} {
    set mychannel [open "|/usr/bin/uname -s"]
    set name [chan gets $mychannel]
    chan close $mychannel

    return $name
}

如果在 Linux 上,會得到的回傳值是 Linux。

我把其它的部份也寫成函式,結果就是下面的 tcl module:
uname-tcl