## Tcl9.0.3/Tk9.0.3 Documentation > Tcl Commands > trace

### Tcl/Tk Applications | Tcl Commands | Tk Commands | [incr Tcl] Package Commands | SQLite3 Package Commands | TDBC Package Commands | tdbc::mysql Package Commands | tdbc::odbc Package Commands | tdbc::postgres Package Commands | tdbc::sqlite3 Package Commands | Thread Package Commands | Tcl C API | Tk C API | [incr Tcl] Package C API | TDBC Package C API

  NAME
    trace — 変数の利用と､命令の利用と､命令の実行を監視する Monitor variable accesses, command usages and command executions
  構文 SYNOPSIS
  説明 DESCRIPTION
    trace add type name ops ?args?
      trace add command name ops commandPrefix
        rename
        delete
      trace add execution name ops commandPrefix
        enter
        leave
        enterstep
        leavestep
      trace add variable name ops commandPrefix
        array
        read
        write
        unset
    trace remove type name opList commandPrefix
      trace remove command name opList commandPrefix
      trace remove execution name opList commandPrefix
      trace remove variable name opList commandPrefix
    trace info type name
      trace info command name
      trace info execution name
      trace info variable name
  用例 EXAMPLES
  SEE ALSO
  KEYWORDS

### NAME

trace — 変数の利用と､命令の利用と､命令の実行を監視する Monitor variable accesses, command usages and command executions

### 構文 SYNOPSIS

trace option ?arg arg ...?

### 説明 DESCRIPTION

この命令は特定の操作が起動される時はいつでも実行されるべきTcl 命令を惹き起こす｡適正な option (短縮しても構わない)は: This command causes Tcl commands to be executed whenever certain operations are invoked. The legal options (which may be abbreviated) are:

trace add type name ops ?args?
  ここで､type は command か execution か variable である｡ Where type is command, execution, or variable.

  trace add command name ops commandPrefix
    リスト ops で与えられる方法の一つで name 命令が修正される時は何時でも commandPrefix が実行される(追加的引数と共に)様に手配する｡ name は命令により使用された通常の名前空間による決定法を使って定める｡もし命令が実在しないと不都合が発信される｡ Arrange for commandPrefix to be executed (with additional arguments) whenever command name is modified in one of the ways given by the list ops. Name will be resolved using the usual namespace resolution rules used by commands. If the command does not exist, an error will be thrown.

    ops はどの操作が対象であるかを指し示し､次の項目の１つ或はそれ以上のリストである｡ Ops indicates which operations are of interest, and is a list of one or more of the following items:

    rename
      追跡されている命令が名前変更されると何時でもcommandPrefix が起動する｡註意すべきは､空文字列への名前変更は削除と看做され､ “rename” では追跡できない｡ Invoke commandPrefix whenever the traced command is renamed. Note that renaming to the empty string is considered deletion, and will not be traced with “rename”.

    delete
      追跡されている命令が削除されると何時でもcommandPrefix が起動する｡命令は rename 命令を使用して命令の名前を空文字列に変更することにより明示的に削除できる｡命令は又､解釈実行機能が削除される時にも削除されるが､追跡は起動できない､理由はそれが起ったときに解釈実行機能がなくなっているから｡ Invoke commandPrefix when the traced command is deleted. Commands can be deleted explicitly by using the rename command to rename the command to an empty string. Commands are also deleted when the interpreter is deleted, but traces will not be invoked because there is no interpreter in which to execute them.

    追跡が発動する時､追跡される操作によってきまる個数の引数が commandPrefix に追記される､それで､実際の命令は次の様になる: When the trace triggers, depending on the operations being traced, a number of arguments are appended to commandPrefix so that the actual command is as follows:

        commandPrefix oldName newName op

    oldName と newName は追跡される命令の現在の(古い)名前とその名前に変えられてしまう名前(空文字列では“削除”操作になる)を与える｡ op は命令上にどの様な操作が遂行されるかを指し示す､そして上で定義した様に rename か delete かの内の一つである｡この追跡操作は消去されていることにより命令を停止する事には使えない｡ Tcl は､一度追跡が完了すると常にその命令を取除こうとする｡再帰的な名前変更や削除は評価されるべき同じ型の更なる追跡を起こさない､そこで､追跡命令の削除は､それそのものが命令を削除する､又､追跡命令の名前変更は､それそのものが命令の名前を変更する､それで更なる追跡の評価は引起さない｡ oldName と newName の両者はそれが現れる場所でどれかの名前空間によって完全に修飾される｡ OldName and newName give the traced command's current (old) name, and the name to which it is being renamed (the empty string if this is a “delete” operation). Op indicates what operation is being performed on the command, and is one of rename or delete as defined above. The trace operation cannot be used to stop a command from being deleted. Tcl will always remove the command once the trace is complete. Recursive renaming or deleting will not cause further traces of the same type to be evaluated, so a delete trace which itself deletes the command, or a rename trace which itself renames the command will not cause further trace evaluations to occur. Both oldName and newName are fully qualified with any namespace(s) in which they appear.

  trace add execution name ops commandPrefix
    リスト ops で示された位置で追跡が起ったことにより name 命令が実行される時は何時でも commandPrefix が実行される様に(追加的引数と共に)手配する｡ name は命令により使用された通常の名前空間による決定法を使って定める｡もし命令が実在しないと不都合が発信される｡ Arrange for commandPrefix to be executed (with additional arguments) whenever command name is executed, with traces occurring at the points indicated by the list ops. Name will be resolved using the usual namespace resolution rules used by commands. If the command does not exist, an error will be thrown.

    ops はどの操作が対象であるかを指し示し､次の項目の１つ或はそれ以上のリストである｡ Ops indicates which operations are of interest, and is a list of one or more of the following items:

    enter
      命令 name が実行される時は何時でも､実際の実行が起る寸前に､ commandPrefix を起動する｡ Invoke commandPrefix whenever the command name is executed, just before the actual execution takes place.

    leave
      Invoke commandPrefix whenever the command name is executed, just after the actual execution takes place.

    enterstep
      手続函数 name の実行の始まりから手続函数が終る迄に実行される全ての Tcl 命令について commandPrefix を起動する｡commandPrefix は実際の Tcl 命令の実行が報告される直前に起動される｡譬えば､もし､ “proc foo {} { puts "hello" }” があると､ enterstep 追跡は “puts "hello"” が実行される直前に起動される｡手続函数を参照していない命令 name に enterstep 追跡を設定すると､結果は不都合にならず単に無視される｡ Invoke commandPrefix for every Tcl command which is executed from the start of the execution of the procedure name until that procedure finishes. CommandPrefix is invoked just before the actual execution of the Tcl command being reported takes place. For example if we have “proc foo {} { puts "hello" }”, then an enterstep trace would be invoked just before “puts "hello"” is executed. Setting an enterstep trace on a command name that does not refer to a procedure will not result in an error and is simply ignored.

    leavestep
      手続函数 name の実行の始まりから手続函数が終る迄に実行される全ての Tcl 命令について commandPrefix を起動する｡commandPrefix は実際の Tcl 命令の実行が報告される直後に起動される｡手続函数を参照していない命令 name に leavestep 追跡を設定すると､結果は不都合にならず単に無視される｡ Invoke commandPrefix for every Tcl command which is executed from the start of the execution of the procedure name until that procedure finishes. CommandPrefix is invoked just after the actual execution of the Tcl command being reported takes place. Setting a leavestep trace on a command name that does not refer to a procedure will not result in an error and is simply ignored.

    追跡が起動されると､追跡される操作に会わせて幾つかの引数が commandPrefix に追加され､そこで､実際の命令は次の様になる: When the trace triggers, depending on the operations being traced, a number of arguments are appended to commandPrefix so that the actual command is as follows:

    enter と enterstep 操作に関して: For enter and enterstep operations:

        commandPrefix command-string op

    Command-string が完全な現在の実行すべき命令を与え( enter 操作の為には追跡命令､ enterstep 操作の為には任意の命令)､それには全ての引数を完全に拡張した形式で含む｡op は命令上にどの様な操作が遂行されるかを指し示し､上で定義した様に enter か enterstep かの内の一つである｡この追跡操作は問題になっている命令を消去することにより､命令の実行を停止する事に使える｡勿論､命令が引続いて実行される時は､ “invalid command(不正な命令)” の不都合が生じる｡ Command-string gives the complete current command being executed (the traced command for a enter operation, an arbitrary command for a enterstep operation), including all arguments in their fully expanded form. Op indicates what operation is being performed on the command execution, and is one of enter or enterstep as defined above. The trace operation can be used to stop the command from executing, by deleting the command in question. Of course when the command is subsequently executed, an “invalid command” error will occur.

    leave と leavestep 操作について: For leave and leavestep operations:

        commandPrefix command-string code result op

    command-string が完全な現在の実行すべき命令を与える( enter 操作の為には追跡命令､ enterstep 操作の為には任意の命令)､それには全ての引数を完全に拡張した形式で含む｡ code は実行した結果の番号を与え､そして result は結果の文字列である｡ op は命令上にどの様な操作が遂行されるかを指し示し､上で定義した様に leave か leavestep かの内の一つである｡註意すべきは､多くの enterstep や leavestep の追跡の生成は直感的でない結果になり得る､理由は一つの追跡から起動された命令が自身を更なる追跡の為の命令の起動に導くかもしれいないから｡ Command-string gives the complete current command being executed (the traced command for a enter operation, an arbitrary command for a enterstep operation), including all arguments in their fully expanded form. Code gives the result code of that execution, and result the result string. Op indicates what operation is being performed on the command execution, and is one of leave or leavestep as defined above.

    Note that the creation of many enterstep or leavestep traces can lead to unintuitive results, since the invoked commands from one trace can themselves lead to further command invocations for other traces.

    同一文脈内の命令としての commandPrefix の実行は追跡された操作を起動する: そこで､ commandPrefix は､もし手続函数から起動されたら､その手続函数内の命令として同一局所内の変数を使う｡この文脈は､追跡が作成された文脈と違うかもしれない｡もし､ commandPrefix が手続函数を起動すると(普通の動作)､追跡操作が起動した命令の局所変数を使いたい時には､手続函数は upvar か uplevel 命令を使う必要がある｡ CommandPrefix executes in the same context as the code that invoked the traced operation: thus the commandPrefix, if invoked from a procedure, will have access to the same local variables as code in the procedure. This context may be different than the context in which the trace was created. If commandPrefix invokes a procedure (which it normally does) then the procedure will have to use upvar or uplevel commands if it wishes to access the local variables of the code which invoked the trace operation.

    commandPrefix が追跡実行中に実行している間､ name の追跡は一時的に無能になる｡これにより､commandPrefix に､なにも他に再度追跡することなく､その本体内で name を実行することを許容する｡もし commandPrefix を実行中に不都合が生じると､命令 name の全体が同じ不都合で戻る｡ While commandPrefix is executing during an execution trace, traces on name are temporarily disabled. This allows the commandPrefix to execute name in its body without invoking any other traces again. If an error occurs while executing the commandPrefix, then the command name as a whole will return that same error.

    name に多重の追跡を設定すると､ enter と enterstep の為に､追跡命令は､元々如何に追跡が作成されたかの逆順で起動される; そして､ leave と leavestep 操作の為に､この追跡命令は最初に作成された順序で起動される｡ When multiple traces are set on name, then for enter and enterstep operations, the traced commands are invoked in the reverse order of how the traces were originally created; and for leave and leavestep operations, the traced commands are invoked in the original order of creation.

    追跡を実行する振舞いは､他の名前空間の中に移入された name 命令の為に現在は定義されない｡ The behavior of execution traces is currently undefined for a command name imported into another namespace.

  trace add variable name ops commandPrefix
    リスト ops で与えられる方法の一つで name 命令が利用される時は何時でも commandPrefix が実行される様に手配する｡ name は通常の変数､配列の要素､配列全体を参照するかも知れない(即ち､ name は括弧索引を伴わない配列の名前かもしれない)｡もし name が配列全体を参照すると､ commandPrefix は配列の要素が操作された時は何時でも起動される｡もし変数が実在しないと作成されるが値は与えられない､そこでその変数は､問合せしている namespace which には見えるが､ info exists の問合せには見えなくなる｡ Arrange for commandPrefix to be executed whenever variable name is accessed in one of the ways given by the list ops. Name may refer to a normal variable, an element of an array, or to an array as a whole (i.e. name may be just the name of an array, with no parenthesized index). If name refers to a whole array, then commandPrefix is invoked whenever any element of the array is manipulated. If the variable does not exist, it will be created but will not be given a value, so it will be visible to namespace which queries, but not to info exists queries.

    ops はどの操作が対象であるかを指し示し､次の項目の１つ或はそれ以上のリストである｡ Ops indicates which operations are of interest, and is a list of one or more of the following items:

    array
      変数がarray 命令経由で利用され又は修正される時は､ array 命令が起動された時点で name が単純変数でない限り､何時でも commandPrefix を起動する｡もし name が単純変数であると､ array 命令経由の利用は追跡を起動しない｡ Invoke commandPrefix whenever the variable is accessed or modified via the array command, provided that name is not a scalar variable at the time that the array command is invoked. If name is a scalar variable, the access via the array command will not trigger the trace.

    read
      変数が読まれた時は何時でも commandPrefix を起動する｡ Invoke commandPrefix whenever the variable is read.

    write
      Invoke commandPrefix whenever the variable is written.

    unset
      変数が消去された時は何時でも commandPrefix を起動する｡変数は明示的に unset 命令によって消去されるか､又は､暗示的に手続函数が戻る時に消去される(その全ての局所変数は消去される)｡変数は又､解釈実行機能が消去された時も消去されるが､追跡は起動されない､理由はそれを実行する解釈実行機能がなくなるから｡ Invoke commandPrefix whenever the variable is unset. Variables can be unset explicitly with the unset command, or implicitly when procedures return (all of their local variables are unset). Variables are also unset when interpreters are deleted, but traces will not be invoked because there is no interpreter in which to execute them.

    追跡が起動する時三つの引数が commandPrefix に追記される､それで､実際の命令は次の様になる: When the trace triggers, three arguments are appended to commandPrefix so that the actual command is as follows:

        commandPrefix name1 name2 op

    Name1は､利用される変数の為の名前を与える｡ これは､ trace add variable命令内で使われている名前と同じである必要はない: upvar命令は手続き函数に異なる名前の下で変数を参照する事を許容する｡ もし､追跡が初めに､配列上に､又は配列要素上に､設定されると name2はその中に配列が影響された索引を提供する｡ この情報は､ name1がスカラーを参照する時にさえ存在する､それは､ 単一配列要素への参照を生成する為にupvar命令が使われると､ 発生し得る｡ もし配列全体が消去され､且つ追跡が一つの要素ではなく配列全体を登録していたら､ name1 は配列名を､ name2 は空文字列を与える｡ op は命令上にどの様な操作が遂行されるかを指し示す､そして上で定義した様に read か write か unset かの内の一つである｡ Name1 gives the name for the variable being accessed. This is not necessarily the same as the name used in the trace add variable command: the upvar command allows a procedure to reference a variable under a different name. If the trace was originally set on an array or array element, name2 provides which index into the array was affected. This information is present even when name1 refers to a scalar, which may happen if the upvar command was used to create a reference to a single array element. If an entire array is being deleted and the trace was registered on the overall array, rather than a single element, then name1 gives the array name and name2 is an empty string. Op indicates what operation is being performed on the variable, and is one of read, write, or unset as defined above.

    同一文脈内の命令としての commandPrefix の実行は追跡された操作を起動する: もし変数がTcl 手続函数の一部として利用されると､ commandPrefix は､同一局所の変数をその手続函数の命令として利用する｡この文脈は､追跡が作成された文脈と違うかもしれない｡もし､ commandPrefix が手続函数を起動すると(普通の動作)､追跡操作が起動した命令の局所変数を使いたい時には､手続函数は upvar か uplevel 命令を使う必要がある｡註意すべきは､ name1 は変数に追跡を設定した時の名前と同じ必要はない; もし upvar 命令で定義した変数を通して利用すると､違いが現れ得る｡ CommandPrefix executes in the same context as the code that invoked the traced operation: if the variable was accessed as part of a Tcl procedure, then commandPrefix will have access to the same local variables as code in the procedure. This context may be different than the context in which the trace was created. If commandPrefix invokes a procedure (which it normally does) then the procedure will have to use upvar or uplevel if it wishes to access the traced variable. Note also that name1 may not necessarily be the same as the name used to set the trace on the variable; differences can occur if the access is made through a variable defined with the upvar command.

    読み書きの追跡の為の､ commandPrefix は追跡した操作の結果に影響を及ぼす為に変数を修正するかもしれない｡もし､ commandPrefix が読み或は書きの追跡の間に変数の値を修正すると､新しい値は追跡した操作の結果として返って来ることになる｡ commandPrefix から返ってきた値は無視される､但し もし何かの種類の不都合を返すと､追跡操作も又追跡命令により返された同じ不都合伝達文を付けて不都合を返す(譬えば､この仕組みは読取り専用の変数の実装に使用することができる)｡書込みの追跡の為に､commandPrefix は変数の値が変化した後に起動される; それは､書込み操作の中で指定された元の値を置き換える為に新しい値を変数に書込むことができる｡読取り専用の変数を実装する為にcommandPrefix は変数の古い値を再保存する必要がある｡ For read and write traces, commandPrefix can modify the variable to affect the result of the traced operation. If commandPrefix modifies the value of a variable during a read or write trace, then the new value will be returned as the result of the traced operation. The return value from commandPrefix is ignored except that if it returns an error of any sort then the traced operation also returns an error with the same error message returned by the trace command (this mechanism can be used to implement read-only variables, for example). For write traces, commandPrefix is invoked after the variable's value has been changed; it can write a new value into the variable to override the original value specified in the write operation. To implement read-only variables, commandPrefix will have to restore the old value of the variable.

    commandPrefix が書込み又は読出し追跡中に実行している間､変数の追跡は一時的に無能になる｡これは､commandPrefix に起動された書込み又は読出しが､再度commandPrefix (又は､何か他の追跡)により起動されなくとも､直接に起ることを意味する｡しかしもし､commandPrefix が変数を消去(unset)すると､消去の追跡が起動される｡ While commandPrefix is executing during a read or write trace, traces on the variable are temporarily disabled. This means that reads and writes invoked by commandPrefix will occur directly, without invoking commandPrefix (or any other traces) again. However, if commandPrefix unsets the variable then unset traces will be invoked.

    消去(unset)の追跡が起動された時､変数は既に削除されている: 追跡なしの未定義が出現する｡手続函数からの返りの理由により消去が起動すると手続函数から返っているとの文脈中で追跡が起動されることになり: 返っている手続函数の枠の棚は最早存在しない｡追跡は消去の追跡の間は不能になってはないので､もし消去追跡命令が新しい追跡を作成しそして変数を利用すると追跡が起動される｡なんであれ消去の追跡の中の不都合は無視される｡ When an unset trace is invoked, the variable has already been deleted: it will appear to be undefined with no traces. If an unset occurs because of a procedure return, then the trace will be invoked in the variable context of the procedure being returned to: the stack frame of the returning procedure will no longer exist. Traces are not disabled during unset traces, so if an unset trace command creates a new trace and accesses the variable, the trace will be invoked. Any errors in unset traces are ignored.

    もし変数の上に多重の追跡があるとそれらは作成された順に起動される､即ち最も最近のものが先になる｡もし一つの追跡が不都合を返すと､その変数の為の更なる追跡は起動されない｡もし､配列要素が追跡を設定し､且つ､配列全体として追跡設定があると､配列全ての追跡が要素のものよりも先に起動される｡ If there are multiple traces on a variable they are invoked in order of creation, most-recent first. If one trace returns an error, then no further traces are invoked for the variable. If an array element has a trace set, and there is also a trace set on the array as a whole, the trace on the overall array is invoked before the one on the element.

    一度作成されると追跡は､下に記述するtrace remove variable 命令により取去られる迄か､変数が消去される迄か､解釈実行機能が削除される迄か､効果が残留する｡配列要素の消去は､何であれ要素の追跡を取除くが､配列全体の追跡は取除かない｡ Once created, the trace remains in effect either until the trace is removed with the trace remove variable command described below, until the variable is unset, or until the interpreter is deleted. Unsetting an element of array will remove any traces on that element, but will not remove traces on the overall array.

    この命令は空文字列を返す｡ This command returns an empty string.

trace remove type name opList commandPrefix
  ここで､ type は command か execution か variable である｡ Where type is either command, execution or variable.

  trace remove command name opList commandPrefix
    もし､ opList と commandPrefix で与えられた操作と命令を伴う命令 name 上に追跡が設定されていると追跡が取除かれ､ commandPrefix は最早起動されることはない｡空文字列を返す｡もし､ name が実在しないと命令は不都合を発信する｡ If there is a trace set on command name with the operations and command given by opList and commandPrefix, then the trace is removed, so that commandPrefix will never again be invoked. Returns an empty string. If name does not exist, the command will throw an error.

  trace remove execution name opList commandPrefix
    もし､ opList と commandPrefix で与えられた操作と命令を伴う命令 name 上に追跡が設定されていると追跡が取除かれ､ commandPrefix は最早起動されることはない｡空文字列を返す｡もし､ name が実在しないと命令は不都合を発信する｡ If there is a trace set on command name with the operations and command given by opList and commandPrefix, then the trace is removed, so that commandPrefix will never again be invoked. Returns an empty string. If name does not exist, the command will throw an error.

  trace remove variable name opList commandPrefix
    もし､ opList と commandPrefix で与えられた操作と命令を伴う変数 name 上に追跡が設定されていると追跡が取除かれ､ commandPrefix は最早起動されることはない｡空文字列を返す｡ If there is a trace set on variable name with the operations and command given by opList and commandPrefix, then the trace is removed, so that commandPrefix will never again be invoked. Returns an empty string.

trace info type name
  Where type is either command, execution or variable.

  trace info command name
    命令 name に設定されている現在の追跡毎に一つの要素になっているリストを返す｡リストのそれぞれの要素は､それ自身が追跡に関する opList と commandPrefix である二つの要素を持つリストである｡もし､ name がいかなる追跡も設定していなければ､この命令の結果は空文字列になる｡もし､ name が実在しなければこの命令は不都合を発信する｡ Returns a list containing one element for each trace currently set on command name. Each element of the list is itself a list containing two elements, which are the opList and commandPrefix associated with the trace. If name does not have any traces set, then the result of the command will be an empty string. If name does not exist, the command will throw an error.

  trace info execution name
    命令 name に設定されている現在の追跡毎に一つの要素になっているリストを返す｡リストのそれぞれの要素は､それ自身が追跡に関する opList と commandPrefix である二つの要素を持つリストである｡もし､ name がいかなる追跡も設定していなければ､この命令の結果は空文字列になる｡もし､ name が実在しなければこの命令は不都合を発信する｡ Returns a list containing one element for each trace currently set on command name. Each element of the list is itself a list containing two elements, which are the opList and commandPrefix associated with the trace. If name does not have any traces set, then the result of the command will be an empty string. If name does not exist, the command will throw an error.

  trace info variable name
    変数 name に設定されている現在の追跡毎に一つの要素になっているリストを返す｡リストのそれぞれの要素は､それ自身が追跡に関する opList と commandPrefix である二つの要素を持つリストである｡もし､name が実在しないか､いかなる追跡も設定していなければ､この命令の結果は空文字列になる｡ Returns a list containing one element for each trace currently set on variable name. Each element of the list is itself a list containing two elements, which are the opList and commandPrefix associated with the trace. If name does not exist or does not have any traces set, then the result of the command will be an empty string.

### 用例 EXAMPLES

大域変数 foo と bar のいずれかが更新された時は何時でも､たとえその時それが異なる局所名を有していても(それは upvar 命令で遂行できる)､伝言文を印刷する｡ Print a message whenever either of the global variables foo and bar are updated, even if they have a different local name at the time (which can be done with the upvar command):

    proc tracer {varname args} {
        upvar #0 $varname var
        puts "$varname was updated to be \"$var\""
    }
    trace add variable foo write "tracer foo"
    trace add variable bar write "tracer bar"

大域変数 foobar は常に大域変数 foo と bar の積を含んでいることを確かめる: Ensure that the global variable foobar always contains the product of the global variables foo and bar:

    proc doMult args {
        global foo bar foobar
        set foobar [expr {$foo * $bar}]
    }
    trace add variable foo write doMult
    trace add variable bar write doMult

Tcl 手続函数の処理の間にどの様な命令が実行されたかの追跡を印刷する: Print a trace of what commands are executed during the processing of a Tcl procedure:

    proc x {} { y }
    proc y {} { z }
    proc z {} { puts hello }
    proc report args {puts [info level 0]}
    trace add execution x enterstep report
    x
      → report y enterstep
        report z enterstep
        report {puts hello} enterstep
        hello

### SEE ALSO

set, unset

### KEYWORDS

read, command, rename, variable, write, trace, unset
Copyright © 1993 The Regents of the University of California.
Copyright © 1994-1996 Sun Microsystems, Inc.
Copyright © 2000 Ajuba Solutions.