Lisp デバッガは、プログラマが、計算を途中で止め (Lisp コードのデバッグを助け る)様々なことができるようにします。通常、(break として知られる) このような状況 では、スタックを調べたり、(ローカルもしくはグローバル) 変数の値を調べたり、そ の値を変更したりします。 break は、実際は (関数呼び出し中の) リカーシブエ ディットであるため、もう一度デバッガを呼ぶことも含め(全く)何でも行なうことがで きます。
デバッガの動きは、 Emacs Editing Manual に (良く)ドキュメント化されていますか ら、ここでそれを繰り返すことはしません。本セクションの残りの部分では Emacs Editing Manual の対応するセクションの内容を知っているものとして話を進めます。
デバッガの処理は実際(実に)シンプルで、C のコードは殆ど含みません - デバッガは (大部分) Lisp で書かれています。
デバッガの行なう基本的な処理が 1つ存在しています。デバッガは複数の異なる条件の もとで break に入ります。この条件とは、ある特定の関数に入った(訳注:enter) 場 合やそれを出た(訳注:exit)場合、エラーの生じた場合、quit シグナルがユーザーの コードで扱われなかった場合等です。 break に入ると、デバッガはスタック(の状態) に関する情報を出力し、ユーザーが(いくつかの)コマンドをタイプするのを待ちます。 ユーザーが明示的に処理(訳注:computation)の異常終了を要求しない限り、デバッガ は呼び出した関数が(正常に呼ばれた場合に返す値を返し)正常な結果になるようアレン ジします。
Function: debug &rest args
この関数は、デバッガに入ります。バッファを *Backtrace* (2 番目のリカーシブ エディットの場合 *Backtrace*<2> 等) という名前にスイッチし、スタックに関す る情報を出力します。この後、(プログラマをデバッガモードであるこのバッファ に置き) リカーシブエディットに入ります。
デバッガで定義されているコマンドの 1 つに continue があり、これはリカーシ
ブエディットを exit し、前のバッファにスィッチバックし、 (普通に)処理を続 行させます。デバッガモードの(その他の)コマンドを次に定義します。
args が non-nil の場合、(それが最初のアーギュメントである場合) 特別な意味 を持つ値が存在しています。それらの値は(通常)デバッガ関数でのみ用いられ、 debug を呼んでいるプログラマが用いることはありません。最初のアーギュメント が nil の場合、残りのアーギュメントは (ただ) Backtrace バッファの先頭に print されるだけのものになります。最初のアーギュメントが特別な値のものでな い場合、アーギュメントは(全て) バッファの先頭に print されます。
特別な値は、
debug
(デバッグされる)関数に enter していることを示すのに用います。デ バッガはバッファの先頭行に Entering: を表示し、 (exit 時にそれも break するよう) debug を呼んだ関数をマークします。 lambda (デバッグされる)関数に enter していることを示すのに用います?? error エラーか quit が出さ(訳注:signal)れ扱われなかったため、デバッガに 入ったことを示すのに用います。エラーが出された場合、変数 debug- on-error は non-nil であるとされます。 quit が出された場合、変数 debug-on-quit は non-nil であるとされます。 Signalling: を表示し、出さ(訳注:signal)れたエラーと signal に対す るアーギュメントとを後ろに付けて表示します。
(let ((debug-on-error t)) (/ 1 0)) ---------- Buffer: *Backtrace* ---------- Signalling: (arith-error) /(1 0) ...
t
用いられている?? バッファの先頭行に Beginning evaluation of call form: を表示します。 nil (プログラマが直接デバッガに入り)バッファの先頭行に残りのアーギュメ ントを表示したい場合、用います。 exit デバッグしている関数が値を返していることを示すのに用います。バッ ファの先頭行に Return value: を表示し、返された値をこれに続けて表
示します。
Command: debug-on-entry function-name
この関数は、 function-name が呼ばれるたびにデバッガを起動するようにしま す。これは関数定義の最初のフォームにフォーム (debug 'debug) を挿入すること で行ないます。
Lisp コードで定義された関数は(インタープリットされるコードであれコンパイル されたコードであれ) どれでもデバッグできます。コマンドである関数もデバッグ できます。関数から呼ばれた場合も、インタラクティブに呼ばれた場合もデバッガ に入ります。 primitive 関数(i.e., C で書かれた関数)はデバッグできません。
インタラクティブに呼ばれた場合、 function-name を求め(ミニバッファに)プロ ンプトを出します。
function-name を返します。同じ関数に対し debug-on-entry を複数回呼んだ場 合、 2 回目の呼び出しは何も行ないません?? 2 回呼ぶと関数 def を kill する バグレポートが出された??
(defun fact (n) (if (zerop n) 1 (* n (fact (1- n))))) => fact (debug-on-entry 'fact) => fact (fact 3) => 6
---------- Buffer: *Backtrace* ---------- Entering: * fact(3) eval-region(4870 4878 t) byte-code("...") eval-list-sexp(nil) (let ...)
eval-insert-last-sexp(nil) * call-interactively(eval-insert-last-sexp) ---------- Buffer: *Backtrace* ----------
(symbol-function 'fact) => (lambda (n) (debug (quote debug)) (if (zerop n) 1 (* n (fact (1- n)))))
Command: cancel-debug-on-entry function-name
この関数は、 function-name に対する debug-on-entry をキャンセルします。
function-name を返します。同じ関数に対し debug-on-entry を複数回呼んだ場 合、 2 回目の呼び出しは何も行ないません?? 2 回呼ぶと関数 def を kill する バグレポートが出された??
インタラクティブに呼ばれた場合、 function-name を求め(ミニバッファに)プロ ンプトを出します。
User Option: debug-on-error
この変数は、 (扱われない)エラーが出さ(訳注:signal)れた場合、デバッガを呼 ぶべきか否かを定めます。 non-nil の場合、エラーごとにデバッガを呼びます (quit はエラーではありません)。 nil の場合、デバッガは呼びません。
User Option: debug-on-quit
この変数は、 quit が出さ(訳注:signal)れ扱われなかった場合、デバッガを呼ぶ べきか否かを定めます。 non-nil の場合、quit シグナルごとにデバッガを呼びま す (quit はエラーではありません)。 nil の場合、デバッガは呼びません (quit は C-g が出すシグナルです)。
User Option: stack-trace-on-error
この変数は、 (扱われない)エラーの後(Lisp が自動的に)バックトレースバッファ を表示するか否かを定めます。 non-nil の場合、エラーが生ずるごとにバックト レースを *Backtrace* という名前の(ポップアップ)バッファに表示します。 nil の場合、バックトレースは表示しません。
バックトレースを表示する場合も、(その)バッファは select されません。 debug-on-entry や debug-on-quit も non-nil の場合、バックトレースを 1つの ウィンドウに表示し、デバッガは別(のウィンドウ)にポップアップします。
Variable: debug-on-next-call
この変数は、 "(次の) eval, apply, funcall の前にデバッガを呼ぶべきか否か" を定めます。デバッガに入ると自動的に nil にリセットされます。
Variable: debugger
この変数の値は、デバッガを起動するために呼ぶ関数です。この値は、複数のアー ギュメントを持ちうる関数(もしくは、より一般的には関数の名前) でなくてはい けません。この関数は、(何らかの)デバッガに入るものとされます。
この関数に渡される最初のアーギュメントは、どのように呼ばれたかを示します。 アーギュメントに関する慣例の詳細は、debug の記述で述べられています。
Command: backtrace
この関数は、今現在 active な(訳注:実行している) Lisp 関数呼び出しのトレー スを print します。これは debug で *Backtrace* バッファを作る際、用いる関 数です。 (どの関数呼び出しが active であるかを調べるため)スタックをアクセ スしなくてはいけないため、この関数は C で書かれています。
(backtrace) > nil -> backtrace() eval-region(7982 7993 #<buffer debugger.texinfo>) byte-code("...") eval-last-sexp((4)) (let ...)
eval-insert-last-sexp((4)) * call-interactively(eval-insert-sexp)
Function: backtrace-debug level flag
この関数は、 level レベル下の eval frame の debug-on-exit フラグを flag に 設定し、(flag が non-nil の場合)その frame を exit する際、デバッガに入る ようにします。
debug-on-exit フラグは、関数呼び出しにおける stack frame 中のエントリーで す。
(通常)この関数はデバッガからのみ呼ばれます。