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
Keywords: FAQ tcl tclX

Archive-name: tcl-usage-QnA-j/part01
Version: 1.2-J1.0
Last-modified: Tue Nov 29 16:12:53 JST 1994
Posting-Frequency: monthly


訳者まえがき

これは,joe@morton.rain.com (Joe Moss) 氏によって管理される "FAQ: comp.lang.tcl Tcl Language Usage Questions And Answers" の日本語 訳です.今回はオリジナルをalcatelアーカイブから取りましたので,ヘッダは ありません(訳者のサイトのNewsシステムは,慢性的に不調な状態にあります). この日本語訳に対するご意見・ご質問・誤りのご指摘などは,訳者まで. また,その他の詳細な情報については,tcl-faq-j/part00 を参照して下さい.


はじめに

本 FAQ ファイルは,Tcl プログラミング言語に関する, 共通的によく聞かれる質問を扱うことを目的としています. このような質問が本文章で整理されることにより, comp.lang.tcl の同じ投稿の繰り返しが減り, より情報的になることを期待します. また,本文書や他の FAQ によって, より多くの人々が Tcl や Tcl ベースのアプリケーションを より便利に使えるようになることも期待します.

この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 からでも入手することができます.

Tcl に関するこれ以上の情報は, Larry Virden (lvirden@cas.org) によって管理されているFAQを参照して下さい. これには,他の利用可能な文書や多くの拡張, サンプルコードなどへのポインタが掲載されています.これもまた,alcatel の /tcl/docs ディレクトリで(ファイル tcl-faq.part0[1-5].gz として)入手でき, また,URL: http://www.cis.ohio-state.edu/hypertext/faq/usenet/tcl-faq/top.html でも見ることができます.

本 FAQ は Tcl に関して扱うものであり, Tk についてのものではないことに注意して下さい. Tk に関しては,Thomas J. Accardo (tja@cpu.com) から投稿されている "Tk Toolkit Q&As" を参照するとよいでしょう. しかしながら,必然的な情報のだぶりもあります. Tk ウィジェットの扱い方に関する最もよく聞かれる質問のいくつかは, Tcl インタプリタの動作自体に対する誤解に起因するものです. こういった問題は,今後もここで扱われます. また,Tcl の扱いの幾つかの例題では, Tk を実行する必要がある場合もあるでしょう.

Tk に依存しない拡張(拡張 Tcl や Expect など,ただし,TkX や expecTk, BLT は除く)の使い方に関する質問と回答もまた,ここで取り扱われます.

この文章のソースは,現在では HTML 形式で管理するようになりました. テキストバージョンに質問番号や質問目次, From や Subject 行を魔法の様に自動的に付加するために,2 つのスクリプト (もちろん,Tcl で書かれています)を通しています. WWW から参照できるバージョンは,変更がある度に更新されますが, ASCII テキストバージョンは月に1度,生成,投稿されるだけです.


質問目次:

  • Q1- 私のマシン上で Tcl を動かすために必要な情報を得るには?
  • Q2- 連想リストや属性リストを生成/使用するには?
  • Q3- Tclで乱数を生成するには?
  • Q4- あるprocから返される複数のパラメータ値を引数に 別のprocを呼ぶには?
  • Q5- procに配列を渡すには?
  • Q6- 外部コマンドを実行し,その出力をパイプで読むには?
  • Q7- 拡張Tclをwishやexpectなどに組み込むには?
  • Q8- スクリプト中で,そこに定義されているプロシージャを削除するには?
  • Q9- upvar によって生成された配列であると連想配列を認識させるには?
  • Q10- 倍精度の7桁以上の精度を得るには?
  • Q11- 非組み込みコマンドの呼出が発生した際に, コマンドラインに戻らない様にするには?
  • Q12- 環境変数を読み書きするには?
  • Q13- 頭に0がついた数字を扱うには?
  • Q14- 作成するアプリケーションでコマンドライン引数を参照するには?
  • Q15- 記述しているスクリプト中の, 例えば case 文のところなどにコメントを入れるには?
  • Q16- バイナリ・データを入出力するには?
  • Q17- シグナルの捕捉や,その他のUnix固有の機能を使うには?
  • Q18- 思う通りにクォートされた文字列を動かすには?
  • Q19- 複数のTclアプリケーション間でプロシージャを共有するには?
  • Q20- リストに挿入された要素を得るには?
  • Q21- ファイル識別子から非ブロック化読み込みを行うには?
  • Q22- ロックさせずにパイプに読み書きするには?
  • Q23- 実行させているバージョンが何だか知るには?
  • Q24- Tclがインストールされていない環境でも動作する スタンドアローン・プログラムを作成するには?
  • Q25- 配列名を保持するのに変数を使うには?
  • Q26- AIX で Tcl/Tk の共有ライブラリを作成するには?
  • Q27- HP-UX で Tcl のコンパイルに成功した人はいませんか?
  • Q28- VMSで Tcl のコンパイルに成功した人はいませんか?
  • Q29- SCO Unix で Tcl をコンパイルするにはどうするの?
  • Q30- tclTest を実行すると format や scan でエラーになるのは何故?
  • Q31- tclTestをIrix 4.0.1 で実行させるとエラーが大量に出るのは何故?
  • Q32- CrayでTclを問題なく走らせた人はいませんか?
  • Q33- NeXTSTEP 3.1に Tcl7.1/Tk3.4をインストールするには?
  • Q34- Tcl/Tk 本のドラフトをプリントアウトできないのは何故でしょう?
  • Q35- SGI Indigo ワークステーションでエラーになったのは何故?
  • Q36- expectをsolaris 2.3で構築するには?
  • Q37- SequentにTcl/Tkを移植するには?
  • Q38- AU/X 3.0で, シンボルテーブルが一杯というメッセージを回避するには?
  • Q39- MS-DOSやMacOSの様な非Unixシステム上でTclをコンパイルするには?
  • Q40- QNXシステム上でTclをコンパイルするには?

  • From: Tcl Q&A
    Subject: Q1- 私のマシン上で Tcl を動かすために必要な情報を得るには?

    Tcl の配布物の中から"porting.notes" というファイル名のファイルを探して見ましょう. これには,これまで多くの人々から寄せられた, 様々なマシンや OS 上で Tcl を動かす際の注釈事項がまとめられています. また,コードに触ったりする前にまず最初に読むべき, "README"というファイルもあります (これは,どんなパッケージにも言えることですけど).

    この文章の終りの方には, 様々なプラットホーム上でインタプリタを構築することに関連した 幾つかの質問と答えが納められています.

    →目次へ

    From: Tcl Q&A
    Subject: Q2- 連想リストや属性リストを生成/使用するには?

    拡張 Tcl の配列や,キー付きリストを使うと良いでしょう.

    例えば,以下のようにプログラムしたなら:

     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
    
    →目次へ

    From: Tcl Q&A
    Subject: Q3- Tclで乱数を生成するには?

    拡張Tclには,これを行うrandomというコマンドがあります. 例えば,0から9までの乱数を生成するならば,
    set random_number [random 10]
    

    また, 乱数生成器の種を設定するsrandomというコマンドもあります.

    すべてTclで書かれた, 幾つかの仮想乱数生成関数がcomp.lang.tclに投稿されています. それらの一覧は,Larryの"tcl-faq/part04"を参照して下さい.

    種に使える値を得るには, 以下のうちの1つ(か,その組合せ)を用いると良いでしょう.

     [pid]
     [file atime /dev/kmem]
     [getclock]                        (拡張Tclのみ)
    
    →目次へ

    From: Tcl Q&A
    Subject: Q4- あるprocから返される複数のパラメータ値を引数に別のprocを呼ぶには?

    y は複数の引数を要求し,x は複数の語を返すとします. Tcl の evalコマンドを使ってやります:
    eval y [x]
    
    →目次へ

    From: Tcl Q&A
    Subject: Q5- procに配列を渡すには?

    もし可能であるならば,グローバル変数を使うよりも, upvarコマンドを試して見るべきです. もし,関数がイベント駆動であるならば,グローバル変数を使わざるを得ませんが.
    # 配列の要素を出力する
    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 は,キーと値の組合せのリストである,キー付きリストと呼ばれる コンセプトを導入していて,ネットワーク経由などでも,値をルーチンに引き 渡すことが出来ます.

    →目次へ

    From: Tcl Q&A
    Subject: Q6- Q6- 外部コマンドを実行し,その出力をパイプで読むには?

    例えば,幾つかのファイルに対して grep でパターンマッチを行うならば, 以下の方法などが考えられます:

    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 つの要素を持つリストとして加えた点に注意して下さい.

    →目次へ

    From: Tcl Q&A
    Subject: Q7- 拡張Tclをwishやexpectなどに組み込むには?

    拡張 Tcl のバージョン 6.7c では, 他のアプリケーションと合体させやすい様に改良されています.

    →目次へ

    From: Tcl Q&A
    Subject: Q8- スクリプト中で,そこに定義されているプロシージャを削除するには?

    プロシージャ名を無名にリネームします.例えば,
    rename procedureName ""
    
    →目次へ

    From: Tcl Q&A
    Subject: Q9- スクリプト中で,そこに定義されているプロシージャを削除するには?

    1992年6月現在,upvarに, 配列の個々の要素を書くことはできません. これは,Ousterhout氏にバグであると確認され,バグリストに置かれています.

    →目次へ

    From: Tcl Q&A
    Subject: Q10- 倍精度の7桁以上の精度を得るには?

    Tcl 6.x では,tclExpr.cモジュールの%gを使っている所を %lfを使うように書き換えます. Tcl 7.x では,換わりにグローバル変数tcl_precisionsetします.

    →目次へ

    From: Tcl Q&A
    Subject: Q11- 非組み込みコマンドの呼出が発生した際に, コマンドラインに戻らない様にするには?

    見付けられないコマンドが呼び出された際には, プロシージャunknownが, (見付けられなかった)コマンド名とその引数を引数にして自動的に呼び出されます. 実際の所,Tclや拡張Tclは,この機能を, コマンドやライブラリの自動読み込みの機能を実現するのに使用しています.

    従って,unknownプロシージャを書き換えれば, 独自の機能拡張を行えます. 望むならば,自動読み込みの機能を削除することさえも可能です.

    →目次へ

    From: Tcl Q&A
    Subject: Q12- 環境変数を読み書きするには?

    例えば,次のように行います.
    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"
        }
    

    →目次へ

    From: Tcl Q&A
    Subject: Q13- 頭に0がついた数字を扱うには?

    Dave Morriss は,次のような感じに組んでしまって,頭を抱えてしまいました.

      set index [expr [exec date +%W]%[llength $pop_server_list]]
    
    なぜなら,8 番目と,9 番目の週でエラーとなってしまうからです. --- それは,08 と 09 は,Tcl では正しい 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]]
    
    の様になります.

    →目次へ

    From: Tcl Q&A
    Subject: Q14- 作成するアプリケーションでコマンドライン引数を参照するには?

    拡張 Tcl や Expect を使っているならば,コマンドライン上で指定さ れたパラメータを,リスト形式のTcl変数argvで参照することができます. 拡張 Tcl の場合は,プログラム名は Tcl変数programNameに格納され, argv[0]には入らないので注意が必要です. Brad Morrison (brad@NeoSoft.com)と Bud Bach (bachww@rtsg.mot.com)の回答に感謝します.

    [訳注:]
    Tcl 7.3/Tk 3.6 では, 既定義変数argcargvが使えます. argcはコマンドライン引数の数, argvには引数の値のリストが格納されます. コマンド名自体はargv[0]にではなく, 変数argv0に格 納されるので注意が必要です. 以下のサンプルを参照して下さい.

    	#!/usr/local/bin/tclsh
    	puts "argv0 = $argv0"
    	puts "argc = $argc"
    	foreach i $argv {
    	    puts "$i"
    	}
           

    →目次へ

    From: Tcl Q&A
    Subject: Q15- 記述しているスクリプト中の,例えば case 文のところなどにコメントを入れるには?

    コメントは,置きたい所にそのまま置くことはできません. そうしたい場合は,コメントを "{" の内側に移動しましょう.例えば,次のように書きます.
    case 1 {
      -1    {
            #
            # 情報が見付けられない場合
            #
            exit 2
            }
       0    {
            #
            # 引数にエラーがある場合
            #
            exit 1
            }
       default    {
            #
            # 望む情報が見付けられた場合
            #
            exit 0
            }
    }
    
    Gerald W. Lester (gwlester@cpu.com) に感謝.

    →目次へ

    From: Tcl Q&A
    Subject: Q16- バイナリ・データを入出力するには?

    拡張 Tcl では,次のように,これを安全に行えます.
    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

    →目次へ

    From: Tcl Q&A
    Subject: Q17- シグナルの捕捉や,その他のUnix固有の機能を使うには?

    拡張Tclは,たくさんのこの手の機能を提供しています. 例えば,拡張Tcl には "signal"コマンドがあります.

    signal action siglist [command]
    ここでactionは, "default", "ignore", "error", "trap", "get"に加えて POSIXの"block"と "unblock"アクションのいずれか (もちろん,POSIX システムでのみ有効). siglistは,記号表現,あるいは数値表現のUnixシグナルのリスト (前置記法 SIG はオプション). commandは,定義するエラー・ハンドラ (あるいは,単に, {puts stdout "そんなキーは押さないで!"} :-).

    "trap" は期待通り動きますし,"error"と"get" は, キーボード・トラバーサルが必要な会話的プログラムでは,とても有効です.

    拡張 Tcl は,forkなどの機能も持っています.

    回答は Brad Morrison (brad@NeoSoft.com)から寄せられました.

    →目次へ

    From: Tcl Q&A
    Subject: Q18- 思う通りにクォートされた文字列を動かすには?

    この問題点を扱った長文の記事が,以下で得られます.

    ftp://ftp.aud.alcatel.com/tcl/docs/README.programmer.gz

    ここに掲載するのは,短い答えです:

    Q. 後になって実行するコマンドを組み立てようとしてるのですが, 空白や特殊文字を値に含む変数で問題が出てしまいます.

    A. コマンドを組み立てる最も安全な方法は,list コマンドを使うことです. そうすれば,リスト構造を壊さずにすみます. 余計なエバリュエータによる評価が行われてしまうこともあるので, ダブルクォートの使用は避けましょう. 例題として, クリックしたら表示しているラベルを出力するボタンを生成するプログラムを 示します.

    間違えた答え #1:
    button $myname -text $label -command "puts stdout $label"
    なぜ?
    それは,もし$labelが空白文字を含むなら, putsコマンドに間違えた数の引数が渡されてしまうからです. $labelが$や[]文字を含むなら, 出力されずに評価されてしまいます.

    良い答え #2:
    button $myname -text $label \
           -command [list puts stdout $label]
    なぜ?
    list$labelの値を適切にクォートするからです.
    Q. 後になって実行するコマンドを組み立てようとしてるのですが, 変数が組み立て時に評価されてしまったり, コマンドの実行時に評価されてしまったりして,思い通りに動いてくれません.

    A. これを行う最も明晰な方法は, 実行時の変数の使用を隠蔽するようにプロシージャを定義することです. そして,前に述べた様に listコマンドを用いてプロシージャの呼び出しを組み立てあげます. (実行中であってもプロシージャの定義は可能です. 別のプロシージャの内部で生成されても, それはグローバルなスコープを持ちます.)

    間違えた答え #1:
    button $myname -text $label -command \
           [list puts stdout $ArrayOfDynamicStuff($label)]
    なぜ?
    配列変数はボタンが生成された時の値で置き換えられてしまい, ボタンがクリックされた時の値とはならないからです. また,コマンドがグローバルなスコープで実行されることにも 注意しなければなりません. そのため, "global ArrayOfDynamicStuff"を コマンドの中に含める必要はありません.

    間違えた答え #2 (バッククォートと list):
    button $myname -text $label -command \
           [list puts stdout \$ArrayOfDynamicStuff($label)]
    なぜ?
    これでは,listコマンドと $ のバッククォートが, 互いに喧嘩してしまいます.結果として全体の振舞いは以下の様になり,
    puts stdout {$ArrayOfDynamicStuff(foo)}
    配列要素の値に対する置換が働かなくなってしまいます.

    いかがわしい答え #3 (バッククォートとダブルクォート):
    button $myname -text $label -command \
           "puts stdout \$ArrayOfDynamicStuff($label)"
    なぜ?
    これは$labelの値が特殊文字や空白文字を含まない時だけ, まともに動きます.

    完全な答え #4 (proc):
           proc doit { i } {
              global ArrayOfDynamicStuff
              puts stdout $ArrayOfDynamicStuff($i)
           }
           button $myname -text $label -command [list doit $label]
    なぜ?
    ボタンのために簡単なTclプロシージャを作ってやる様にしておけば, ちゃんと動作してくれます. 何故なら,凝ったクォーティングをする必要をなくしてくれますし, ボタンから起動される処理の仕様変更も,容易になります.
    Q. プロシージャに可変個数の引数を渡そうとしてるのですが, $argsを正しく展開するところで,つまってしまいます.

    A. evalとダブルクォートを組み合わせて使おうとするのは, 止めましょう. なぜなら,そうすると,余計な評価が起動されてしまうからです. evalコマンドは,その引数が1つ以上の場合は,それらを1つに連結します. そのため,ダブルクォートで1つに括ってやる必要が,まったく無くなります. 前述のbuttonの例を拡張して見ましょう.

    間違えた答え #1:
           proc mybutton { myname label args } {
              button $myname -text $label \
                  -command [list puts stdout $label] $args
           }
    なぜ?
    変数$argsに格納されている mybuttonへの全ての追加引数は, 1つのリスト要素にグループ化されてしまっています. しかしながら,buttonコマンドはその引数に, サブリストではなく個々の引数を要求するからです.

    間違えた答え #2:
           proc mybutton { myname label args } {
              eval "button $myname -text $label \
                      -command [list puts stdout $label] $args"
           }
    なぜ?
    ダブルクォートは,$argsと同じように, $labelの展開を可能にします. そのため,$labelの値に空白文字が含まれるなら, buttonコマンドには, 正しくない引数並びが渡されることになってしまいます.

    良い答え #3:
           proc mybutton { myname label args } {
              set cmd {button $myname -text $label \
                       -command [list puts stdout $label]}
              eval $cmd $args
           }
    なぜ?
    evalは,最初に 2 つの引数を連結して, 次にその結果をインタプリタを介して実行します. これは,$cmd$argsから, 外側のカリー括弧を外して, 2つの変数の全ての要素を1つのリストにすると考えられます. $labelは,1回しか評価されません. そして,putコマンドも正しく動きます. さらに,argsが入れられる度にも,1回しか処理しません.
    Q. なんで if/while/for文で 文法エラーになってしまうのでしょう.

    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) からのコントリビュートです.

    →目次へ

    From: Tcl Q&A
    Subject: Q19- 複数のTclアプリケーション間でプロシージャを共有するには?

    明示的にファイルをsourceするのではなく, Tclライブラリを作るようにしましょう.

    Step 1. ファイルを共有ディレクトリに置きます.
    Step 2. "ライブラリ" のための,tclIndex を作ります.
    私は Makefile 中に,次のように書いています.
           install.index:
               (cd ${DESTDIR}/tclscripts/lib; \
               echo 'source /usr/local/lib/tcl/init.tcl;\
    	   auto_mkindex . *.tk' | tcl ; exit 0)
           
    Step 3. 作成した Tcl スクリプトに, ライブラリを参照させるようにします.
    例えば,以下のようにします.
           # local additions
           lappend auto_path /usr/local/lib/tcl_local \
                $env(RDS_TCL_SCRIPTS)/lib
           
    このようにすれば, スクリプトはプロシージャをライブラリの中から参照しようとし, "unknown"コマンドが 自動的にプロシージャを読み込んでくれます.
    この記述は,Joe VanAndel (vanandel@ncar.ucar.edu)からの コントリビュートです.

    →目次へ

    From: Tcl Q&A
    Subject: Q20- リストに挿入された要素を得るには?

    よく,なぜ
    linsert $list 0 ..
    
    と実行したのに,結果に .. が挿入されていないのかと聞かれます.

    Jesper Blommaskog (d9jesper@dtek.chalmers.se)が, 以下のように答えています.

    lappend以外のリスト操作では,戻り値を保存しなければなりません. これは,list,lindex,lrange,lreplaceに 当てはまります.

    これは,ひょっとしたらやりたかった事が正しく動く例です.

    set list [ linsert $list 0 .. ]
    
    →目次へ

    From: Tcl Q&A
    Subject: Q21- ファイル識別子から非ブロック化読み込みを行うには?

    Frank Smith (frank@arraysystems.nstn.ns.ca)によると, 拡張 Tcl を持っているなら,
    read $fileId [fstat $fileId size]
    
    のようにして実現可能です. これは,fileIdからその時点で読み込める最大のバイト数を読み込み, 結果としてブロック化しません.

    →目次へ

    From: Tcl Q&A
    Subject: Q22- ロックさせずにパイプに読み書きするには?

    標準入出力パッケージは, (入出力する)文字をバッファリングして 不必要なシステムコールを行わなくて済むようにすることで, 処理速度を最適化しています. これは会話的な使用には不適切ですので, 標準入出力はその振舞いをファイルが端末である場合には変更します. (ですが)パイプに書き込む時には,端末に書き込んでいる訳ではないので, 書き込んだ出力はバッファリングされてしまいます. 同様に,パイプの向こうにある他のプログラムがその応答を出力する時にも, バッファリングされてしまいます. 結果として,パイプの両端のプログラムは, 互いに入力を待って立往生してしまいます. これを解決するには,Tcl ではflushコマンド, C ではfflush()を使ってパイプをフラッシュすることです. もっとも, しばしば,パイプラインの端のプログラムの制御が出来ない場合もあります. その様な場合は,解決する唯一の解は,仮想端末(pty)を使う事です. が,これはそう簡単に行えることではありません.

    これは標準の Tcl ではサポートされていませんが,expect では, spawnコマンドで ptyを開いてコマンドを起動する機能をサポートしています.

    →目次へ

    From: Tcl Q&A
    Subject: Q23- 実行させているバージョンが何だか知るには?

    だれも答えてくれる人はいない様ですが,大丈夫. Tcl 自身が,そのバージョンを答えてくれます. 以下のように打ち込んで見ましょう.
    info tclversion
    
    また,Tk のバージョンは,以下のようにして知ることが出来ます.

    puts $tk_version
    
    その他の拡張では,他の手段があるでしょう.

    →目次へ

    From: Tcl Q&A
    Subject: Q24- Tclがインストールされていない環境でも動作する スタンドアローン・プログラムを作成するには?

    Earle Lowe (lowee@cpsc.ucalgary.ca) は,次のように答えてます:

    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 を用いた,インタプリタ型言語としての使用)法で用い, コードを実行させる時には, コンパイルされたスタンドアローンプログラムを生成する様にすることも可能です.

    [訳注:]
    訳者が理解しているところでは,TkWWW が,この技を使っています.
    →目次へ

    From: Tcl Q&A
    Subject: Q25- 配列名を保持するのに変数を使うには?

    Eric Bleeker (ericbl@paramount.nikhefk.nikhef.nl)が 書く所によれば:

    ひょっとしたら,こんな風に書いていませんか:

    % set foo "e;bar baz"e;
    bar baz
    % foreach aap $foo {
    	set $aap(1) "e;something"e;
    }
    can't read "e;aap(1)"e;: variable isn't array
    
    これは,Tclが配列要素"aap(1)"を, 存在してもいないのに置換しようとしているのです. これを解決するには,以下のようにします.
    % foreach aap $foo {
    	set [set aap](1) "e;something"e;
    }
    
    この場合は,2 つの配列"e;bar"e;と "e;baz"e;は生成されます.

    →目次へ

    From: Tcl Q&A
    Subject: Q26- AIX で Tcl/Tk の共有ライブラリを作成するには?

    Dov Grobgeld (dov@menora.weizmann.ac.il) が, AIX 3.1.5で,TclとTkの共有ライブラリを作る方法を発表しています.

    Tclでは:
           cc -o tkshar.o *.o -bE:tclshar.exp -bM:SRE -berok \
                     -lX11 -lm
           ar r libtclshr tclshar.o
           
    Tkでは:
           cc -o tkshar.o *.o -bE:tkshar.exp -bM:SRE -berok \
                     -Ltcl -lX11 -lm -ltclshr
           ar r libtkshr tkshar.o
           
    ここで tckshar.exp と tkshar.exp は,外部関数のリストです.

    AIX と IBM のフォントの問題もあります. X サーバを修正するパッチをIBMから入手する必要があり, そうすれば,フォント関連が動きます.

    →目次へ

    From: Tcl Q&A
    Subject: Q27- HP-UX で Tcl のコンパイルに成功した人はいませんか?

    ポーティング ノートを参照して下さい. また,Configure が互換バージョンのopendir()を (コンパイルに)使うべきだと判断してしまうけど, dirent.h が存在していないという問題の報告が幾つかなされています. これは,globでエラーを引き起こします. TclXのreaddirでも同様です.

    tcl 7.3では,opendirの互換ファイルを削除する変更を行いましょう. そして,-DNO_DIRENT, -DUSE_DIRENT2を削除すれば,問題は解決します.

    →目次へ

    From: Tcl Q&A
    Subject: Q28- VMSで Tcl のコンパイルに成功した人はいませんか?

    1993年5月4日に, John Kimball (jkimball@src.honeywell.com) から寄せられた情報によれば, 彼はTcl 6.7とTk 3.2をVMS 5.5 上にポーティングすることに成功したそうです. ファイルの情報はカタログを参照して下さい.

    →目次へ

    From: Tcl Q&A
    Subject: Q29- SCO Unix で Tcl をコンパイルするにはどうするの?

    "#undef select"をtkEvent.cに加え, main.cの460行目あたりのTK_EXCEPTION の参照を削除します.

    Tkは,そのウィジェット立体表示のために, 表示枠のカラー確保のための独自の仕組みを使っています. これがTkを,"Pseudo Color" ディスプレイ・クラスで, 16セルのカラーマップのマシン上で実行する際に問題となります.

    8bitプレーンを使えないならば, ディスプレイ・クラスを "StaticColor" にする様に, サーバを "-static"(Xsco) や "-analog"(Xsight)オプション指定で立ち上げるとよいでしょう. これは,カラーマップを完全に読み込みのみとし, 要求された色にできるだけ最も近い色を返すようにします.

    この情報は, Keith Amann (Keith_Amann@stortek.com)から寄せられました.

    →目次へ

    From: Tcl Q&A
    Subject: Q30- tclTestを実行するとformatやscanでエラーになるのは何故?

    この(scanf/printfの)問題は,多くのシステムで見られます. これに関しては,あまり神経質になる必要はありません --- `より高度な'機能が使えないだけです. もしあなたがCのハッカーならば,同じ問題に出喰わす筈です.

    実例をあげるならば,printf("%Ng, double_value)とstrtod("+",&terminal)は, 誤った結果をもたらします.

    →目次へ

    From: Tcl Q&A
    Subject: Q31- tclTestをIrix 4.0.1 で実行させるとエラーが大量に出るのは何故?

    これは,4.0.1のオプティマイザのバグで, 4.0.2では修正されています. tclVar.cをオプション-O0(最適化無し)でコンパイルして下さい.

    →目次へ

    From: Tcl Q&A
    Subject: Q32- CrayでTclを問題なく走らせた人はいませんか?

    ポーティング・ノートの変更点に関する記述を参照して下さい. また,Booker C. Bense (benseb@grumpy.sdsc.edu)は, バージョン 3.0.1.6 ではキャラクタ型のポインタの深刻な問題があり, Tclがクラッシュすると報告しています. バージョン 3.0.2.1 を使うと多少はマシですが, formatコマンドの些細なバグと, scanコマンドの深刻な問題は残るそうです.

    →目次へ

    From: Tcl Q&A
    Subject: Q33- NeXTSTEP 3.1に Tcl7.1/Tk3.4をインストールするには?

    この問題に関しては,以前,大きな議論の元となりました.以前の記述を, この分野のオーソリティと思える方からの解説に置き換えることとします.

    Robert Nicholson (robert@steffi.demon.co.uk) によれば:

    これはTCL7.1 と TK3.4 を対象とします.

    これは Thomas Funke のエントリです.

    ★ TCL7.1のNeXTへのインストール法

    tcl7.1をNeXTSTEP 3.1にインストールするには,以下のようにします:
    configure を既定義のCPPで実行:
    ボーンシェルを実行するために,"e;sh"e;と打ち込みます. そして,以下のようにタイプします.
           CPP='cc -E' ./configure
           
    Makefile を編集:
    tmpnam.oをCOMPAT_OBJSに追加:
           COMPAT_OBJS = getcwd.o waitpid.o strtod.o tmpnam.o
           
    この時,NeXTライブラリlibsys_a.aで供給されるものに対して, strtodtmpnamを区別するために, 何か適当な名前に変更したいと思うでしょう. これを行うためには,AC_FLAGSに,以下の行を付け加えることで出来ます.
           -Dstrtod=newstrtod -Dtmpnam=newtmpnam
           
    名称変更された関数の定義は,compat/*.cにあります.
    全てが正しく動くかどうかをチェックするには, tclshを起動し,以下を実行します.
    % expr {"e;0"e; == "e;+"e;} 
    0
    
    間違えたstrtod関数を用いていたならば,返り値は1になり, 深刻なエラーとなります.正確なエラーは無視します.

    ★ TK3.4 の NEXTSTEP 3.1 へのインストール法

    Tk3.4 の中にもstrtod関数の呼び出しがあるので, 前述の../tcl-7.1/compat/strtod.oにリンクを張り, AC_FLAGSに-Dstrtod=newstrtodを付け加える必要があります.

    注意: Tk の raise 試験は, ウィンドウマネージャにtvtwmを使っていると失敗します. この試験を通すためには,twmやfvwmなどに変更する必要があります.

    →目次へ

    From: Tcl Q&A
    Subject: Q34- Tcl/Tk 本のドラフトをプリントアウトできないのは何故でしょう?

    John Ousterhout (John.Ousterhout@Eng.Sun.COM) によると:
    私のところに届いてる知らせによると, 多くの人々が,この本の一部の印字出力で問題を抱えているようです.

    古いバージョンの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/'
           
    →目次へ

    From: Tcl Q&A
    Subject: Q35- SGI Indigo ワークステーションでエラーになったのは何故?

    Gordon Lack (gml4410@ggr.co.uk)によれば, SGIのCコンパイラには変数引数の扱いにいくつかのエラーがあるそうです.

    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=\"e;${TCL_LIBRARY}\"e;
    
    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のバージョンが欲しいならば,メールして下さい.

    →目次へ

    From: Tcl Q&A
    Subject: Q36- expectをsolaris 2.3で構築するには?

    Jeff Abramson (jra@hrcms.jazz.att.com)が語るには:

    SunPro cc 2.0.1を使ってもgcc 2.5.8を使っても問題はありません. SunProならば,次のようにします.

       CC=cc ./configure --prefix=あなたの選んだディレクトリ
       make CC=cc
    
    gccならば,以下の通りです.
       CC="gcc -fwritable-strings" ./configure \
    	  --prefix=あなたの選んだディレクトリ
       make CC="gcc -fwritable-strings"
    
    →目次へ

    From: Tcl Q&A
    Subject: Q37- SequentにTcl/Tkを移植するには?

    Andrew Swan (aswan@soda.berkeley.edu)によって解明されました.

    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)が発生します. これら以外もありますが,すべてのコンパイルはきれいに終了し, すべての試験にもパスします.

    →目次へ

    From: Tcl Q&A
    Subject: Q38- AU/X 3.0で,シンボルテーブルが一杯というメッセージを回避するには?

    AU/X 上でのソースのコンパイルが終ったならば, デフォルトのテーブルのアロケーションを拡張する -A {factor}引数をリンカに指定しなければなりません. {factor}は,デフォルトのアロケーションの何倍にするかを指定します. -A 2を試してみましょう. この移植に関するこれ以上の詳細は, Walter B. Kulecz 博士 (wkulecz@medics.jsc.nasa.govに 連絡すると良いでしょう.

    →目次へ

    From: Tcl Q&A
    Subject: Q39- MS-DOSやMacOSの様な非Unixシステム上でTclをコンパイルするには?

    Larry VirdenのFAQの,tcl-faq/part1やtcl-faq/part4 を参照すると, 関連するツールや移植の完了品, この問題を扱っているメーリングリストなどの情報が得られます.

    →目次へ

    From: Tcl Q&A
    Subject: Q40- QNXシステム上でTclをコンパイルするには?

    Steve Furr (furr@qnx.com) が示す所によれば:

    QNX 上で Tcl を動かすためにしたことをまとめるならば,

    →目次へ

    FAQ の終り