Newsgroups: fj.lang.tcl,fj.archives.answers Subject: [comp.lang.tcl] Tcl Language Usage Questions And Answers Distribution: fj Followup-To: fj.lang.tcl Reply-To: taguchi@aic.co.jp Expires: Fri Apr 14 00:00:00 JST 1995 Keywords: FAQ tcl tclX Archive-name: tcl-usage-QnA-j/part01 Version: 1.4-J1.0 Last modified: Fri Mar 24 13:51:17 1995 Posting-Frequency: monthly
この日本語訳に対するご意見・ご質問・誤りのご指摘などは,訳者まで. また,その他の詳細な情報については,tcl-faq-j/part00 を参照して下さい.
このFAQは,Joe Moss (joe@morton.rain.com)により管理され, 毎月 comp.lang.tcl と news.answers に投稿され,また, ftp.aud.alcatel.com (198.64,191,10) の /tcl/docs ディレクトリや,World Wide Webページ http://route.psg.com/tcl.html からでも入手することができます.
本 FAQ は Tcl に関して扱うものであり, Tk についてのものではないことに注意して下さい. Tk ツールキットに関しては,Thomas J. Accardo (tja@cpu.com) から投稿されている FAQを参照するとよいでしょう (他のTclに関するFAQに関しては, 後述の質問「Tclに関する情報をもっと知りたいのですが」参照). しかしながら,必然的に情報がだぶる場合もあります. Tk ウィジェットの扱い方に関する最もよく聞かれる質問のいくつかは, Tcl インタプリタの動作自体に対する誤解に起因するものです. こういった問題は,今後もここで扱われます. また,Tcl の扱いの幾つかの例題では, Tkのウィジェットを実行する必要がある場合もあるでしょう.
Tk に依存しない拡張(拡張 Tcl や Expect など,ただし,TkX や expecTk, BLT は除く)の使い方に関する質問と回答もまた,ここで取り扱われます.
この文章のソースは,現在では HTML 形式で管理するようになりました. テキストバージョンに質問番号や質問目次, From や Subject 行を魔法の様に自動的に付加するために,2 つのスクリプト (もちろん,Tcl で書かれています)を通しています. WWW から参照できるバージョンは,変更がある度に更新されますが, ASCII テキストバージョンは月に1度,生成,投稿されるだけです.
Webで情報サーフィンできるなら,以下の2つがスタート点としてよいでしょう. それは, http://www.sco.com/IXI/of_interest/tcl/Tcl.htmlと, http://web.cs.ualberta.ca/%7Ewade/HyperTcl/です.
もちろん,配付品のソースコードそれ自体にも, 多くのドキュメントが含まれています. 正式版は7.3版で,β版の7.4b2も入手できます.これらは, ftp://ftp.cs.berkeley.edu/ucb/tcl/から入手可能です.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
この文章の終りの方には, 様々なプラットホーム上でインタプリタを構築することに関連した 幾つかの質問と答えが納められています.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
これらの機能のより詳細を解説したドキュメントがあります. 拡張Tclの配付品に含まれる, TclCommandWritingマンページを参照すると良いでしょう. これはまた,WWWで, http://psg.com/~joem/CmdWrite.htmlからみる事もできます.
LarryのTcl FAQの第2部や,Tcl参考文献録もまた, その他の参考文献について述べています.
標準Tclに数々の拡張を組み込んだり,タイマやファイル・イベント,Xイベントや, expectを介した仮想ttyからの駆動,Tkでのアイドル・コールバックのハンドルに 関しては,組み込みTkを参照するとよいでしょう.以下から入手できます. ftp://ftp.std.com/pub/drh/et1_0.tar.gz
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
int
Tcl_AppInit(interp)
Tcl_Interp *interp; /* Interpreter for application. */
{
/* ... */
if (Tcl_Init(interp) == TCL_ERROR) {
return TCL_ERROR;
}
/* ... */
}
「foo拡張」を追加するには,
次のようにfooの初期化関数の呼び出しを追加してやります.
int
Tcl_AppInit(interp)
Tcl_Interp *interp; /* Interpreter for application. */
{
/* ... */
if (Tcl_Init(interp) == TCL_ERROR) {
return TCL_ERROR;
}
if (Foo_Init(interp) == TCL_ERROR) {
return TCL_ERROR;
}
/* ... */
}
より詳細な情報は,Tcl_AppInitのマンページや,
tclAppInit.cファイル自体を参照すると良いでしょう.
(前述の)単純な回答はすべての場合に動作するものではない,というのが, より完全な回答です.多くの拡張は,より複雑な改造と, その拡張の使用に依存した組み込み方を必要とします.
拡張Tclを組み込みたい場合,Tcl_AppInitは, その配付に含まれるものを用いねばなりません. またプログラムをリンクする際には,標準Tclライブラリより前に拡張Tclの ライブラリをリンクしなければなりません.例えば:
cc -o mytclsh mytclXAppInit.c -ltclx -ltcl ...あるいは,Tkを組み込んだインタプリタでは:
cc -o mywish mytkXAppInit.c -ltkx -ltk -ltclx -ltcl ...その他の手段としては,Make-A-Wishのような, 拡張を組み合わせる手助けをしてくれるパッケージや, 他のよく使われる拡張と組み合わせるさいに使用することのできる設定ファイルを 含んだ拡張も存在します.例えば,Sven Delmas によって書かれた幾つかの拡張は, 指定された拡張を組み込んだインタプリタを構築するMakefileを生成するための, configureのオプションを指定することができます. これらのパッケージの所在地に関しては,LarryのFAQのpart04〜05を参照して下さい.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
loadコマンドの文法自体は,既に考え出されています. 後は,数多くのプラットホーム上での実装の問題となっています (プラットホーム依存の種々の問題が存在するのです).
以下は,1993年6月14日にJhon Ousterhoutによって書かれたメッセージからの 引用です.
[1993 Tcl]ワークショップにて,私達は動的ローディングの簡単なTclコマンド・
インタフェースの標準化を決定しました.コマンドの文法は以下の通り:
load <file>
ここで<file>は,libtcl.soの様な,動的に読み込まれるオブジェクト・ ファイルの名前です.この名前の部分は,それぞれの システムローカルな設定によって変わり得るでしょうが,先の例ではtclの様に, パッケージのプリフィックスの部分をパッケージ名とします.
loadコマンドは,指定されたオブジェクトファイルを読み込み,
ファイル名からパッケージのプリフィックス部分を取り出して,
プロシージャ<prefix>_Initを実行します.
ここで<prefix>は,最初の1字を大文字化したパッケージ・プリフィックスです.
例えば,Tcl_Init,Dp_Init,Tclx_Initなどが考えられます.
読み込み可能なパッケージは,(Tcl_Interp *)1つを引数として取る
初期化プロシージャを含んでいなければなりません:
int Dp_Init(Tcl_Interp *interp);
初期化プロシージャは,そのパッケージに含まれる全てのTclコマンドをインタプリタに 追加し,加えてその他のパッケージ固有の初期化処理を行います. その返値は標準Tcl完了コードやエラーメッセージ,あるいはインタプリタの戻値で, loadコマンドの返り値として用いられます.幾つかのプラットホーム上での実装は, 既に利用可能(例えばShellパッケージ)です. 詳細は,ソフトウェアカタログ(LarryのFAQのpart05)をカタログを参照するか, Kevin Kenny が1994年Tclワークショップに書いた論文: http://crdis1.ge.com/papers/gecrd/mtl/mdip/tcl94/00header.htmlを 参照して下さい. いずれこれらが,標準配付に組み込まれることが期待されます.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
TCL/Tk が存在していてもいなくても関係なくどこででも動作できる スタンドアローンのプログラムを作りたいならば, もう少し作業する必要があります.
基本的には,これにはまず, TCL初期化ファイルをC文字列に変換してやることからはじめます. そして,Tcl_Init()やTk_Init()を呼ぶ代わりに, 変換された C 文字列を引数にTcl_Eval()を呼んでやります.
Alexei Rodriguez (alexei@cis.ufl.edu)が作成した, wish_compiler パッケージを以下から入手することを勧めます. ftp://ftp.aud.alcatel.com/tcl/code/wish_compiler.shar.gz
このパッケージにはtcl2cコンバータが入っていて, その使用法の説明もついて来ます.
Makefile のちょっとした技を使えば, TCL/Tk の目的通りの使用 (様々な種類の wish を用いた,インタプリタ型言語としての使用)法で用い, コードを実行させる時には, コンパイルされたスタンドアローンプログラムを生成する様にすることも できるでしょう.他の選択肢として,「組み込みTk」を利用することも可能です. これは, ftp://ftp.std.com/pub/drh/et1_0.tar.gzから入手できます.
- [訳注:]
- 訳者が理解しているところでは,TkWWW が,この技を使っています.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
幾つかの技が知られていますが,もっとも一般的なのは, Tclではコマンド行も含めてバックスラッシュ{\}が継続行の印として使える, という機能を利用したものです. 例えば,
#!/usr/local/bin/tclsh puts "Hello World"とするかわりに,以下のように書く事もできます.
#! /bin/sh
# 次の行は/bin/shでは実行されるが,Tclではコメント扱い \
exec tclsh $0 ${1+"$@"}
puts "Hello World"
こうすることで,実際にtclshが何処にインストールされているかに関係なく
(ユーザの環境変数PATHにインストールされたパスが含まれている必要はありますが),
動作させることができます.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
実に多くの人々が様々なシステムの上で, 非常に幅広い用途のためにTclを使用しているのだ,ということを考えに 入れねばなりません. また,Tclは元もと, プログラマがその作成するアプリケーションに必要なスクリプト言語をいちいち 作成する手間を削減するために設計された, 最低限のプログラミングの構成と枠組を提供する 組み込み用の言語であることも忘れてはなりません.
とは言うものの,コアTcl言語はここ数年で大きく発展して来ました. 追加された機能のうちの幾つかは,他で開発された拡張から組み込まれたものです. 拡張によって提供される機能がTclの全てのユーザにとって嬉しいと思われた場合, JhonはコアTclにそれを組み込んで来ました. 例えば,連想リストやファイル入出力コマンド(と,ファイルハンドラ), unknownプロシージャや,標準Tclに組み込まれる前の拡張Tclの諸機能が例として あげられます.Tk 4.0では(そして,Tk4.0b2では現在), Tcl 7.x/Tk 3.xとは別の作者が開発した addinputとphotoウィジェットの機能と同等のものが組み込まれています.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
例えば,以下のようにプログラムしたなら:
keylset ttyFields ttyName tty1a keylset ttyFields baudRate 57600 keylset ttyFields parity stripここで "echo $ttyFields" を実行すると,以下を得ます:
{ttyName tty1a} {baudRate 57600} {parity strip}
あるいは,配列を使って以下のようにする手もあります.
set ttyFields(ttyName) tty1a set ttyFields(baudRate) 57600 set ttyFields(parity) strip
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
set random_number [random 10]
また, 乱数生成器の種を設定するsrandomというコマンドもあります.
すべてTclで書かれた, 幾つかの仮想乱数生成関数がcomp.lang.tclに投稿されています. それらの一覧は,Larryの"tcl-faq/part04"を参照して下さい.
種に使える値を得るには, 以下のうちの1つ(か,その組合せ)を用いると良いでしょう.
[pid] [file atime /dev/kmem] [getclock] (拡張Tclのみ)
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
eval y [x]
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
# 配列の要素を出力する
proc show_array arrayName {
upvar $arrayName myArray
foreach element [array names myArray] {
puts stdout "${arrayName}($element) = $myArray($element)"
}
}
set arval(0) zero
set arval(1) one
show_array arval
上に示したように,プロシージャから配列を返させるには,
配列名を引数として与えてやるだけです.
配列に対して行ったどのような変更操作も,親(呼出元)の配列に反映されます.
拡張 Tcl は,キーと値の組合せのリストである,キー付きリストと呼ばれる コンセプトを導入していて,ネットワーク経由などでも,値をルーチンに引き 渡すことが出来ます.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
karl@NeoSoft.com (Karl Lehenbauer) が書く所によれば:
set files [glob /home/cole/stats/*]
proc parseInfo { site } {
global files
#
# site is chosen from a listbox earlier
#
set in [open [concat "|/usr/bin/grep $site $files"] r]
while {[gets $in line]<-1} {
puts stderr $line
}
catch {close $in}
}
問題点: マッチした文字列が,ディレクトリ順に戻ら*ない*.
一方, もしリターン・コードをチェックし,かつ,コマンドの出力を使いたいならば, Kevin B. Kenny (kennykb@dssv01.crd.ge.com)の書く所によれば:
if [catch {exec ls} data] {
# execでエラーが起きたならば,その終了ステータスが$errorCodeに返る.
} else {
# execが正常終了
}
# どんな場合でも,`data' には子プロセスの出力全てが格納される.
Karl Lehenbauer (karl@NeoSoft.com) がerrorCodeを,
文字列 "CHILDSTATUS",
子プロセスのプロセスID,
子プロセスの終了ステータスの
3 つの要素を持つリストとして加えた点に注意して下さい.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
rename procedureName ""
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
tcl_precisionを1〜17の範囲で
setします.例えば:% expr 4*atan(1) 3.14159 % set tcl_precision 0 can't set "tcl_precision": improper value for precision % set tcl_precision 3 3 % expr 4*atan(1) 3.14 % set tcl_precision 16 16 % expr 4*atan(1) 3.141592653589793 % set tcl_precision 18 can't set "tcl_precision": improper value for precisionTcl 6.xでは,tclExpr.cモジュール中で%gの代わりに%lfを使うように 書き換えねばなりません.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
従って,unknownプロシージャを書き換えれば, 独自の機能拡張を行えます. 望むならば,自動読み込みの機能を削除することさえも可能です.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
set olddisplay $env(DISPLAY) set env(DISPLAY) unix:0答えてくれた Joel Fine (joel@cs.berkeley.edu)に感謝します.
環境変数が存在しているかどうかを調べるのは,次のようにします.
if [info exists env(VARNAME)] {
# 環境変数が定義されているので,それを使う.
set value $end(VARNAME)
} else {
# 環境変数が設定されていないのでデフォルト値を使う.
set value "the default value"
}
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
set index [expr [exec date +%W]%[llength $pop_server_list]]08と09は,Tclでは正しい8進数ではないため, 1年のうち,8番目と9番目の週でエラーが発生してしまうのです. 実際には,Tclは頭に0がついた数を8進数として評価しようとし, それが失敗した場合は(8や9は,8進数には含まれない数字なので), 浮動小数点数として評価しようとします. が,%(剰余)関数はオペランドが整数でなければなりません. このため,エラーとなります.
幾つかの解がありえます. George A. Howlett (george.howlett@att.com) によれば:
set wknum [format "%g" [exec date +%W]] set index [expr [exec $wknum%[llength $pop_server_list]]Fred Feirtag <feirtag@wave.nrl.navy.mil> の解は:
set index [expr (1[exec date +%W]-100)%[llength $pop_server_list]]Dan R. Schenck <schendr@Texaco.COM> からは:
set index [expr [string trimleft [exec date +%W] 0]%[llength $pop_server_list]]Jay Goldberg (jayg@accessware.com) は, (日付を扱う)この場合には,上記の全ては動作するが, 一般的には動かないこともあり得ることを指摘しています.
むしろ,以下のコマンド:
regsub 0+(.+) 元の文字列 \\1 新しい文字列を使って先頭の 0 を除去すべきでしょう.先の例に当てはめるならば,
regsub 0+(.+) [exec date +%W] \\1 weeknum
set index [expr $weeknum%[llength $pop_server_list]]
の様になります.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
#! /usr/local/bin/tclsh
if { $argc != 2 } {
puts stderr "$argv0: Usage: $argv0 <infile> <outfile>"
exit 1
}
set infile [lindex $argv 0]
set outfile [lindex $argv 1]
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
{"
の内側に移動しましょう.例えば,次のように書きます.
case 1 {
-1 {
#
# 情報が見付けられない場合
#
exit 2
}
0 {
#
# 引数にエラーがある場合
#
exit 1
}
default {
#
# 望む情報が見付けられた場合
#
exit 0
}
}
Gerald W. Lester (gwlester@cpu.com) に感謝.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
set infp [open "|compress -dc $fileName"] set outfp [open "|gzip -c $newFileName" w] copyfile $infp $outfpコードの例を提供してくれた karl@NeoSoft.com (Karl Lehenbauer) に感謝.
標準 Tcl でバイナリ・データを 1 文字として扱う方法は,
以下で見つけることができます.
ftp://ftp.aud.alcatel.com/tcl/code/binary-io-hack.shar.gz
この他にも,バイナリデータの扱いを可能にするtclbinとBinarIOという 2種類の拡張が存在します.前者は構造体データを扱えるという利点があり, 後者はバイナリ・データ・ストリームでより効率良く動作する利点があります.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
signal"コマンドがあります.
default", "ignore",
"error", "trap",
"get"に加えて
POSIXの"block"と
"unblock"アクションのいずれか
(もちろん,POSIX システムでのみ有効).
siglistは,記号表現,あるいは数値表現のUnixシグナルのリスト
(前置記法 SIG はオプション).
commandは,定義するエラー・ハンドラ
(あるいは,単に,
{puts stdout "そんなキーは押さないで!"} :-).
拡張 Tcl は,forkなどの機能も持っています.
回答は Brad Morrison (brad@NeoSoft.com)から寄せられました.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
$$varの場合,ドル記号の後の最初の文字が不正文字(次のドル記号)であるので, 変数名が存在しない事になり,変数置換は働きません (2番目のドル記号はそのまま残ります). そして残りのドル記号のための構文解析が開始され,その右側が変数名として 扱われます.このため,直ちに2番目のドル記号以降が変数置換され, 構文解析はそれ以降の置換がないかどうかを調べにいってしまいます. それ以降何もないならば,インタプリタを通したこのパスによる置換は 終了します(1回のみ行われることに注意).
evalコマンドはその引数をインタプリタに通します.そこで,2回目のパスを インタプリタに通すためにevalを使う事ができ,そうすれば$$varを動かす事が できるでしょう:
% set a 5 5 % set var a a % puts $$var # 動かない $a % eval puts $$var # 動く.--- けど危険. 5
ですが,変数varの内容に特殊な文字(スペースやセミコロンなど)が 含まれていると,問題が発生してしまうでしょう.
よりよい方法は,1引数のみ与えられた場合のsetコマンドの振舞を応用し, コマンド置換を変数置換に組み合わせて使用するのです:
% puts [set $var] # 安全に動作. 5また,実際にはコマンド置換(一度に1組の[]にしか働かない)だけを使っても できます:
% puts [set [set var]] # 同じように動作 5
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
ここに掲載するのは,短い答えです:
Q. 後になって実行するコマンドを組み立てようとしてるのですが, 空白や特殊文字を値に含む変数で問題が出てしまいます.
A. コマンドを組み立てる最も安全な方法は, list コマンドを使うことです. そうすれば,リスト構造を壊さずにすみます. 余計なエバリュエータによる評価が行われてしまうこともあるので, ダブルクォートの使用は避けましょう. 例題として, クリックしたら表示しているラベルを出力するボタンを生成するプログラムを 示します.
button $myname -text $label -command "puts stdout $label"
button $myname -text $label \
-command [list puts stdout $label]
A. これを行う最も明晰な方法は, 実行時の変数の使用を隠蔽するようにプロシージャを定義することです. そして,前に述べた様に listコマンドを用いてプロシージャの呼び出しを組み立てあげます. (実行中であってもプロシージャの定義は可能です. 別のプロシージャの内部で生成されても, それはグローバルなスコープを持ちます.)
button $myname -text $label -command \
[list puts stdout $ArrayOfDynamicStuff($label)]
button $myname -text $label -command \
[list puts stdout \$ArrayOfDynamicStuff($label)]
puts stdout {$ArrayOfDynamicStuff(foo)}
配列要素の値に対する置換が働かなくなってしまいます.
button $myname -text $label -command \
"puts stdout \$ArrayOfDynamicStuff($label)"
proc doit { i } {
global ArrayOfDynamicStuff
puts stdout $ArrayOfDynamicStuff($i)
}
button $myname -text $label -command [list doit $label]
A. evalとダブルクォートを組み合わせて使おうとするのは, 止めましょう. なぜなら,そうすると,余計な評価が起動されてしまうからです. evalコマンドは,その引数が1つ以上の場合は,それらを1つに連結します. そのため,ダブルクォートで1つに括ってやる必要が,まったく無くなります. 前述のbuttonの例を拡張して見ましょう.
proc mybutton { myname label args } {
button $myname -text $label \
-command [list puts stdout $label] $args
}
proc mybutton { myname label args } {
eval "button $myname -text $label \
-command [list puts stdout $label] $args"
}
proc mybutton { myname label args } {
set cmd {button $myname -text $label \
-command [list puts stdout $label]}
eval $cmd $args
}
A. ひょっとして,
wish: set foo bar
wish: if {$foo == bar} {puts stdout bar}
syntax error in expression "$foo == bar"
の様に書いてはいないでしょうか.
これでは,文字列としても変数としても評価されません. 式中のオペランドとしての文字列は, ダブルクォートか中括弧で括ってやらねばなりません.
wish: if {$foo == "bar"} {puts stdout bar}
や
wish: if {$foo == {bar}} {puts stdout bar}
の様に書き換えましょう.
どちらを選ぶかは,展開させたいかどうかで決めて下さい.
この記述は,Jesper Blommaskog (d9jesper@dtek.chalmers.se) からのコントリビュートです.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
install.index:
(cd ${DESTDIR}/tclscripts/lib; \
echo 'source /usr/local/lib/tcl/init.tcl;\
auto_mkindex . *.tk' | tcl ; exit 0)
# local additions
lappend auto_path /usr/local/lib/tcl_local \
$env(RDS_TCL_SCRIPTS)/lib
このようにすれば,
スクリプトはプロシージャをライブラリの中から参照しようとし,
"unknown"コマンドが
自動的にプロシージャを読み込んでくれます.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
linsert $list 0 ..と実行したのに,結果に .. が挿入されていないのかと聞かれます.
Jesper Blommaskog (d9jesper@dtek.chalmers.se)が, 以下のように答えています.
lappend以外のリスト操作では,戻り値を保存しなければなりません. これは,list,lindex,lrange,lreplaceに 当てはまります.
これは,ひょっとしたらやりたかった事が正しく動く例です.set list [ linsert $list 0 .. ]
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
read $fileId [fstat $fileId size]のようにして実現可能だそうです. これは,fileIdからその時点で読み込める最大のバイト数を読み込み, 結果としてブロック化しません.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
これは標準の Tcl ではサポートされていませんが,expect では, spawnコマンドで ptyを開いてコマンドを起動する機能をサポートしています.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
info tclversionまた,Tk のバージョンは,以下のようにして知ることが出来ます.
puts $tk_versionその他の拡張では,他の手段があるでしょう(例えば拡張Tclでは, "infox version"でバージョン情報が得られます).
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
ひょっとしたら,こんな風に書いていませんか:
% set foo "bar baz"
bar baz
% foreach aap $foo {
set $aap(1) "something"
}
can't read "aap(1)": variable isn't array
これは,Tclが配列要素"aap(1)"を, 存在してもいないのに置換しようとしているのです. これを解決するには,以下のようにします.
% foreach aap $foo {
set [set aap](1) "something"
}
この場合は,2 つの配列"bar"と "baz"は生成されます.別の形式として,以下のような形も考えられます.
% foreach aap $foo {
set ${aap}(1) "something"
}
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
cc -o tkshar.o *.o -bE:tclshar.exp -bM:SRE -berok \
-lX11 -lm
ar r libtclshr tclshar.o
cc -o tkshar.o *.o -bE:tkshar.exp -bM:SRE -berok \
-Ltcl -lX11 -lm -ltclshr
ar r libtkshr tkshar.o
AIX と IBM のフォントの問題もあります. X サーバを修正するパッチをIBMから入手する必要があり, そうすれば,フォント関連が動きます.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
tcl 7.3では,opendirの互換ファイルを削除する変更を行いましょう. そして,-DNO_DIRENT, -DUSE_DIRENT2を削除すれば,問題は解決します.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
Tkは,そのウィジェット立体表示のために, 表示枠のカラー確保のための独自の仕組みを使っています. これがTkを,"Pseudo Color" ディスプレイ・クラスで, 16セルのカラーマップのマシン上で実行する際に問題となります.
8bitプレーンを使えないならば, ディスプレイ・クラスを "StaticColor" にする様に, サーバを "-static"(Xsco) や "-analog"(Xsight)オプション指定で立ち上げるとよいでしょう. これは,カラーマップを完全に読み込みのみとし, 要求された色にできるだけ最も近い色を返すようにします.
この情報は, Keith Amann (Keith_Amann@stortek.com)から寄せられました.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
実例をあげるならば,printf("%Ng", double_value)と strtod("+",&terminal)は誤った結果をもたらします.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
Robert Nicholson (robert@steffi.demon.co.uk) によれば:
これはTCL7.1 と TK3.4 を対象とします.
これは Thomas Funke のエントリです.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
CPP='cc -E' ./configure
COMPAT_OBJS = getcwd.o waitpid.o strtod.o tmpnam.o
この時,NeXTライブラリlibsys_a.aで供給されるものに対して,
strtodとtmpnamを区別するために,
何か適当な名前に変更したいと思うでしょう.
これを行うためには,
AC_FLAGSに以下の行を付け加えることで出来ます.
-Dstrtod=newstrtod -Dtmpnam=newtmpnam
名称変更された関数の定義は,compat/*.cにあります.
% expr {"0" == "+"}
0
間違えたstrtod関数を用いていたならば,返り値は1になり,
深刻なエラーとなります.精度に関するエラーは無視します.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
注意: Tk の raise 試験は, ウィンドウマネージャにtvtwmを使っていると失敗します. この試験を通すためには,twmやfvwmなどに変更する必要があります.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
私のところに届いてる知らせによると, 多くの人々が,この本の一部の印字出力で問題を抱えているようです.
古いバージョンのTranscriptスプーラ・ソフトウェアには, ページが逆順になったPostScriptファイルの中では, 別のencapsulated PostScriptファイルを扱えないものがあるようです. これらは,ページ構造をごっちゃにする傾向があり, 最初のEPSファイルのところで,エラーになってしまいます. 第2部にはスクリーンダンプを載せるために, 沢山のEPSファイルが埋め込まれています. もし,このファイルを印字出力できないなら, ページ逆順出力が可能となってるかどうかを見て下さい. もしそうであるならば,利用しているシステムのウィザードに言って, 一時的に不能にしてもらいましょう. これで,出力可能になる筈です. あるいはスプールソフトウェアを経由せずに, 直接プリンタに送る手を考えるのもよいでしょう (例えば,プリンタの継ってるシリアルポートに, 直接catしてしまうとか).他にも,次の助言が寄せられています.
組み込まれた図は,行の区切りに LF ではなく CR を使用しているため,
これが問題の原因となる場合があります.
これらを LF に変換して見ましょう.
tr '\015' '\012' < book.p2.ps > fixedbook.p2.ps
そして:
これはオリジナルの投稿者の責任ではありませんが,
出力紙にA4を使っている国で,
Dataproducts LZR1260E の様なプリンタを使用している場合,
印字用紙サイズが縦方向に引き延ばされてしまうことがあります.
これは,他のFramemakerで生成されたファイルでも発生します.
疑いもなく PS インタプリタのバグでしょう.
修正には,A4用紙の大きさを編集してやります.
以下のシェルスクリプトは,これらの問題を両方とも修正します.
#!/bin/sh
cat $1 | tr '\015' '\012' | \
sed '/FMDOCUMENT$/s/612 792/595 842/'
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
tclVar.cは,IRIX C 4.0.1では,変数に関するバグのため, 引数-O0でコンパイルされねばなりません.
Makefile のルール指定を以下のように書き換えてやります.
# GGR SG needs -O0 for varargs at 4.0.1
CC_SWITCHES0 = -O0 -I. -I${SRC_DIR} ${AC_FLAGS} ${MATH_FLAGS} \
${GENERIC_FLAGS} ${PROTO_FLAGS} ${MEM_DEBUG_FLAGS} \
-DTCL_LIBRARY=\"${TCL_LIBRARY}\"
tclVar.o: tclVar.c
$(CC) -c $(CC_SWITCHES0) $<
Peter NEELIN (neelin@pet.mni.mcgill.ca)は,
次のような注意をしてます.
私は,ファイルConfig.mkを次のように変更して, TclX 7.3aをSGI(irix4.0.5)でコンパイルしました.
71c71 < CFLAGS=-cckr -D__GNU_LIBRARY__ --- > #CFLAGS= 106,107c106,107 < TCL_PLUS_BUILD=TCL_PLUS < CCPLUS=g++ --- > #TCL_PLUS_BUILD=TCL_PLUS > CCPLUS=CC 191,193c191 < MAN_DIR_SEPARATOR= < < LIBOBJS=strftime.o --- > #MAN_DIR_SEPARATOR=.-D__GNU_LIBRARY が,srandom問題を解決しますが, 思うに,-cckrがwaitpidでプロトタイプ・エラーを起こします (汚いですが,とりあえず動きます). strftimeがなぜ必要だったかは,忘れてしまいました.
私の作成した Config.mkのバージョンが欲しいならば,メールして下さい.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
SunPro cc 2.0.1を使ってもgcc 2.5.8を使っても問題はありません. SunProならば,次のようにします.CC=cc ./configure --prefix=あなたの選んだディレクトリ make CC=ccgccならば,以下の通りです.CC="gcc -fwritable-strings" ./configure \ --prefix=あなたの選んだディレクトリ make CC="gcc -fwritable-strings"
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
TclとTk双方で,非ANSIのSequent ccではなく,gccを用います.
Tclでは,数学ライブラリに,2つの問題があります. 第1に,Sequentの数学ライブラリが,'fmod'関数を含んでいないことです. 私はfmodのソースをftp.uu.netから入手し, サブディレクトリcompatに入れました. そして,それをMakefileに追加しました. fmodは,'isnan'と'finite'関数を内部で使用していますが, tclが無限とnanをサポートするとは信じなかったので, それらはコメントアウトしただけです.
数学ライブラリのもう1つの問題は, そのライブラリ中に'tanh'関数のコピーが2つ, 含まれてしまっていることです. "ar"を使ってライブラリをオブジェクトに分解し, 再度組み立て直して,tanhのコピーを取り去ってしまえば, 簡単にfixできます.
この様な変更を行えば,Tclのコンパイルはきれいに終了し, 試験も,scanの試験以外はすべて通ります. どうも,Dynixでは,*scanf関数が壊れてる様です. この問題は,8進数の終りで確認できます. 私はちょうど,この問題に取り掛かったところです. 解決策は,*scanf関数のソースを見付けだし, それを使うことになるでしょう.
Tkをコンパイルするために,私はwchar_tのようなものを定義した, 新しいバージョンのstddef.hを作らねばなりませんでした. 私はそれを別のインクルード・ディレクトリにコピーし, そのディレクトリを最初に指定して,それが参照されるようにしました. Tkでも数学ライブラリの問題 (tanh)が発生します. これら以外もありますが,すべてのコンパイルはきれいに終了し, すべての試験にもパスします.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
QNX 上で Tcl を動かすためにしたことをまとめるならば,
- _POSIX_SOURCE 指定を,パス名長を示すために行う.
- VARARGS の定義の変更を行う.こうすれば,Watcom ANSI C コンパイラで, 可変長引数の関数が使えるようになる.
- QNX で定義されたエラーコードとの衝突を解決する.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ
#! /usr/home/誰かのホーム/とっても/なが〜い/パス/tclsh
# スクリプトの本体
なんてのは,エラーを発生する場合があり得ます.
tclshの実行ファイルを他のディレクトリに移動したり, シンボリックリンクを張って,パスを短くするとよいでしょう. 別の解法としては,パスをまったく指定しないという手もあります. これを行う方法は,質問 「tclshがインストールされている場所に関係なく,スクリプトを動作させるには?」 の回答を参照して下さい.
→一般情報目次へ →プログラミング目次へ →移植情報目次へ