[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

B. GNU Emacsの内部構造

この章では、 稼動中のEmacs実行可能形式を どのようにEmacs Lispライブラリをプリロードしたままダンプするのか、 どのように記憶領域を割りつけるのか、 そして、 Cのプログラマが興味をもつようなGNU Emacsのいくつかの内部構造について 述べます。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

B.1 Emacsを作る

この節では、 Emacsの実行可能形式を作るときに起きている諸段階について説明します。 この種のことはメークファイルが自動的に行なってくれるので、 Emacsを作ってインストールするときに知っておく必要はありません。 この情報はEmacsの保守に関係あります。

`src'ディレクトリでCのソース・ファイルをコンパイルすると、 `temacs'という実行可能ファイルができますが、 これをbare impure Emacsといいます。 これにはEmacs LispインタプリタとI/Oルーチンがありますが、 編集コマンドはついていません。

コマンド`temacs -l loadup'では、 本当に実行ができるEmacs実行可能ファイルをつくるのに、 `temacs'を使います。 この引数は`temacs'に、 ファイル`loadup.el'中で指定したLispファイル群を評価させる、 ということを指示しています。 このファイル群で通常のEmacs編集環境を準備すると、 Emacsはbareではなくなりますが、まだimpureではあります。

標準Lispファイル群の読込みには相当時間がかかります。 幸運にも、 Emacsを起動するたびにこれを繰り返すことはありません。 `temacs'は、 このファイル群をプリロードした`emacs'という実行可能プログラムを ダンプすることができます。 `emacs'はもうこのファイルのロードがいらないので、 とても速く立ち上がります。 普通にインストールされるのはこちらのEmacsです。

`emacs'を作るには、 コマンド`temacs -batch -l loadup dump'を使います。 この`-batch'`temacs'が 端末のデータを初期化しないようにしています。 これでダンプ後のEmacsの端末情報が空のままになります。 引数`dump'`loadup.el'にしたがって`emacs'という 新しい実行可能ファイルをダンプしています。

オペレーティング・システムによっては、 ダンプのできないことがあります。 こういうシステムでは、 Emacsを使うたびに、 `temacs -l loadup'というコマンドで始める必要があります。 これにはけっこう時間がかかりますが、 Emacsを立ち上げるのは高々日に1回か、 ログ・アウトしないなら週に1回でしょうから、 この時間もそれほど深刻な問題ではありません。

`site-load.el'ライブラリを書いて プリロードするファイルを追加することができます。 追加ファイル用の場所をあけるために、 `src/puresize.h'中のPURESIZEの値を 増やす必要があることもあります (十分な大きさになるまで20000ずつ増やしてみてください)。 しかしながら、 追加ファイルのプリロードの利点はマシンが速くなるにつれて減ってきています。 最近のマシンではだいたい、 そんなに得策ではありません。

ダンプ前に実行するほかのLisp式を`site-init.el'という ライブラリに書いて指定します。 しかしながら、 ユーザが通常の無修正のEmacsに期待する振舞いを変更する場合は、 ユーザが望むときに優先できるように`default.el'に置く方が いいでしょう。See section 立ち上がりの際の一連の動作一覧

`loadup.el'が新しい実行可能ファイルをダンプする前に、 Snarf-documentationを呼び出して(see section 説明文字列へのアクセス)、 プリミティブ関数とプリロードした関数(と変数)を定義したファイルから 説明文字列を探し出します。 `emacs'実行可能ファイルを小さくするために、 説明文字列は実行可能ファイルから取り除かれます。See section 説明文字列の基礎

Function: dump-emacs to-file from-file

この関数は、 Emacsの現在の状態を実行可能ファイルto-fileにダンプします。 これは(通常はファイル`temacs'の) from-fileからシンボルを取ります。

すでにダンプしてしまったEmacsでこの関数を使う場合、 まずcommand-line-processednilにしなければ うまくいきません。See section コマンド行引数

Command: emacs-version

この関数は、 走行中のEmacsのバージョン番号を示す文字列を返します。 バグ報告にこの文字列を含めると役に立ちます。

 
(emacs-version)
  ⇒ "GNU Emacs 19.29.1 (i386-debian-linux) \
 of Tue Jun  6 1995 on balloon"

対話的に呼び出されると、この関数は、エコー領域に同じ情報を印字します。

Variable: emacs-build-time

この変数の値は、ローカルなサイトでEmacsが作られた時刻です。

 
emacs-build-time
     ⇒ "Tue Jun  6 14:55:57 1995"
Variable: emacs-version

この変数の値は、走行中のEmacsのバージョン番号です。 これは"19.29.1"といった文字列になります。

以下の二つの変数はEmacsのバージョン19.23まではなかったため、 今のところそれほど役には立ちませんが、 私たちは将来これが役に立つであろうことを期待しています。

Variable: emacs-major-version

整数で表わしたEmacsの主バージョン番号です。 Emacsバージョン19.29では19という値になります。

Variable: emacs-minor-version

整数で表わしたEmacsの副バージョン番号です。 Emacsバージョン19.29では29という値になります。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

B.2 純粋記憶領域

Emacs Lispには、 ユーザの作るLispオブジェクト用に 通常記憶領域(normal storage)純粋記憶領域(pure storage) の2種類の記憶領域があります。 通常記憶領域はEmacsの各セッションで作られた新しいデータの すべてを保持する領域です。 通常記憶領域については次節を参照してください。 純粋記憶領域はプリロードされる標準Lispファイル中のデータで、 実際のEmacsの使用中に変化することのないものにたいして使われます。

純粋記憶領域は、 `temacs'が標準のLispライブラリをプリロードするときに 割りつけられます。 ファイル`emacs'中で、 これは(オペレーティング・システムが許すかぎり)読出し専用なので、 マシンで同時に走る全Emacsジョブでメモリ空間を共有することができます。 純粋記憶領域は、Emacsのコンパイル時に固定量が割りつけられ、 拡張することはできません。 プリロード・ライブラリで足りなくなると`temacs'は落ちてしまいます。 こうなると、 ファイル`src/puresize.h'PURESIZEという コンパイル時パラメータを増やすしかありません。 追加のライブラリをプリロードするか、 標準のライブラリに機能を追加するのでないかぎり、 こうなることはまずありません。

Function: purecopy object

この関数は、純粋記憶領域中のobjectの複製を作り、それを返します。 文字列は、同じ文字群をもつものを純粋記憶領域中にただ新しく作ることで 複製を行ないます。 ベクタとコンス・セルの内容は、再帰的に複製します。 マーカを複製するよう要求すると、エラーを通知します。

Emacsが作られダンプされた後、この関数は、空操作になります。 通常は、ファイル`emacs/lisp/loaddefs.el'だけで呼び出されますが、 プリロードすると決めた場合にはこれを呼び出しているパッケージも少しあります。

Variable: pure-bytes-used

この変数の値は、これまで割りつけられた純粋記憶領域のバイト数です。 普通ダンプ後のEmacsで、 この数は存在する純粋記憶領域の総量に非常に近くなります。 もしそうでないときには、割りつける量を少なくできます。

Variable: purify-flag

この変数は、 defunが純粋記憶領域に関数定義の複製を 作るべきか否かを定めます。 非nilの場合、 関数定義は純粋記憶領域に複製されます。

(これらの関数を共有可能で回収不能であるようにするため) 最初Emacsを作るときに基本的な全関数をロードする間、 このフラグはtになっています。 実行可能なプログラムとしてEmacsのダンプを行なうと、 ダンプ前や後の値にかかわらず常にnilに設定されます。

Emacsの走行中にこのフラグを変更してはいけません。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

B.3 ガベージ・コレクション

プログラムがリストを作ったり、 (ライブラリをロードして)ユーザが新しい関数を定義したり場合、 それらは通常記憶領域に置かれます。 通常記憶領域が足りなくなった場合、 Emacsはオペレーティング・システムに それ以上のメモリを1kバイトのブロックで 割りつけるよう要求します。 割りつけられたブロックは、それぞれある1種類の型用に用いられます。 つまり、シンボル、コンス・セル、 マーカなどはメモリ中の異なるブロックにわけられることになります (ベクタ、長い文字列、 バッファおよびそれ以外の一部の非常に大きな編集用の型は、 各オブジェクトごとに割りつけられ、 短い文字列は8kバイトのブロックに詰められます)。

記憶領域をある期間だけ用いて、その後(たとえば)バッファをkillしたり、 オブジェクトに対する最後のポインタを消去したりすることにより、 開放することは、 非常に一般的なことです。 Emacsでは、この放棄された記憶領域を再生する ガベージ・コレクタ(garbage collector)が提供されています (この名前は伝統的なもので、 この機能の直感的なたとえとしては「ゴミ再利用」"garbage recycler"の方が いいかもしれません)。

ガベージ・コレクタは、 Lispプログラムから用いることのできるすべてのLispオブジェクトをスキャンし、 印をつけることで処理を行ないます。 はじめにすべてのシンボル、 その値と対応する関数定義、 現在スタック上に存在するデータは用いられているものであると仮定します。 これらを通して間接的に到達可能なオブジェクトも すべて用いられているという刻印を押します。

印づけが終わったとき、 刻印のないものはすべてガベージです。 Lispプログラムやユーザが何をしようとも、 もはやここへ到達する方法がないため、 ここを使うことは不可能です。 この空間は再利用してもほかと影響しません。 ガベージ・コレクタの第2の「掃き出し」("sweep")段階では、 この場所の再利用を行ないます。

この「掃き出し」段階において、 用いられてないコンス・セル、シンボル、マーカは、 将来の割りつけ用にフリーリスト(free list)につなげられます。 使用中の文字列はなるべく少ない8kブロックに収まるようまず圧縮され、 その後、空いた8kブロックは解放します。 ベクタ、バッファ、ウィンドウ、そのほか大きなオブジェクトは、 個々にmallocfreeを用いて割りつけと解放を行ないます。

Common Lisp注意書き:ほかのLispと異なり、GNU Emacs Lispでは フリーリストが空になった場合にガベージ・コレクタは呼ばれません。 そのかわり、GNU Emacs Lispは、 ただ単にオペレーティング・システムへもっと多くの記憶領域を割りつけするよう要求し、 gc-cons-thresholdバイト使われるまで処理を続けます。

これは、陽にガベージ・コレクタを呼び出すことによって、 Lispプログラムのある部分を実行中にガベージ・コレクタが動かないことを (プログラムの一部が次のガベージ・コレクションを引き起こすほど 大きな空間を消費しないことを前提にして)保証できます。

Command: garbage-collect

このコマンドはガベージ・コレクションを行ない、 用いられている記憶領域の量に関する情報を返します (ガベージ・コレクションは、 前のガベージ・コレクションからgc-cons-thresholdバイト以上Lispデータが用られた場合、 自動的に行なわれます)。

garbage-collectは以下の情報を含むリストを返します。

 
((used-conses . free-conses)
 (used-syms . free-syms)
 (used-markers . free-markers)
 used-string-chars 
 used-vector-slots
 (used-floats . free-floats))

(garbage-collect)
     ⇒ ((3435 . 2332) (1688 . 0)
           (57 . 417) 24510 3839 (4 . 1))

次の表は各要素の説明です。

used-conses

使用中のコンス・セルの個数。

free-conses

オペレーティング・システムから空間を得てはいるが、 今のところ使われていないコンス・セルの個数。

used-syms

使用中のシンボルの個数。

free-syms

オペレーティング・システムから空間を得てはいるが、 今のところ使われていないシンボルの個数。

used-markers

使用中のマーカの個数。

free-markers

オペレーティング・システムから空間を得てはいるが、 今のところ使われていないマーカの個数。

used-string-chars

文字数で測った全文字列の長さの合計。

used-vector-slots

既存のベクタの要素数の合計。

used-floats

使用中の浮動小数点数の個数。

free-floats

オペレーティング・システムから空間を得てはいるが、 今のところ使われていない浮動小数点数の個数。

User Option: gc-cons-threshold

この変数の値は、ガベージ・コレクションが行なわれた後、 次のガベージ・コレクションが自動的に呼ばれるまでに用いることのできる、 記憶領域のバイト数です。 コンス・セルは8バイト、 文字列は1文字当り1バイト足す数バイトのオーバーヘッド、 などのように数えます。 バッファの内容は勘定に入れません。 それ以降は、 次にLisp評価子を呼び出すときをのぞき、 この閾値をこえるまでガベージ・コレクションがおこりません。

この閾値の初期値は300,000です。 もし大きな値を設定すると、ガベージ・コレクションは起こりにくくなります。 ガベージ・コレクションに使われる時間は減りますが、 メモリの総使用量は増加します。 多量のLispデータを作るようなプログラムを使う場合には、 このようにしたくなるかもしれません。

ガベージ・コレクションの回数を増やすため、 10,000以上の小さな値に設定することもできます。 これを10,000以下の値に設定しても、次のガベージ・コレクションまでしか効果はありません。 そのときにgarbage-collectはこれを10,000に戻します。

Function: memory-limit

この関数は、 Emacsが割りつけた最後のバイトのアドレスを1024で割ったものです。 1024で割っているのは値がLisp整数の範囲に収まるようにするためです。

メモリ使用量により影響を受ける動作の決定にこれを使うことができます。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

B.4 Emacsのプリミティブを書く

Lispプリミティブとは、Cで実装したLisp関数のことです。 LispでCの関数が呼び出せるようにするインタフェースの詳細を、 Cのマクロで扱っています。 Cのコードの書きかたを本当に理解する唯一の方法は、 ソースを読むことですが、 ここではある程度の情報を示しておきます。

特殊形式の例としてorの定義を`eval.c'から取りました (通常の関数も同様に一般的な形をしています)。

 
DEFUN ("or", For, Sor, 0, UNEVALLED, 0,
  "Eval args until one of them yields non-nil, then return that value.\n\
The remaining args are not evalled at all.\n\
If all args return nil, return nil.")
  (args)
     Lisp_Object args;
{
  register Lisp_Object val;
  Lisp_Object args_left;
  struct gcpro gcpro1;

  if (NULL (args))
    return Qnil;

  args_left = args;
  GCPRO1 (args_left);

  do
    {
      val = Feval (Fcar (args_left));
      if (!NULL (val))
        break;
      args_left = Fcdr (args_left);
    }
  while (!NULL (args_left));

  UNGCPRO;
  return val;
}

DEFUNマクロに対する引数の詳細な説明から始めましょう。 見本を以下に示します。

 
DEFUN (lname, fname, sname, min, max, interactive, doc)
lname

これはLispシンボルの名前で、定義する関数の名前となります。 前の例の場合これはorです。

fname

これは、この関数に対するCの関数名です。 これはCコードからこの関数を呼ぶ際、用いられる名前です。 慣例として名前はLisp名の先頭に`F'をつけ、 Lisp名におけるダッシュ(-)をすべてアンダースコアに変えたものです。 したがって、 Cコードからこの関数を呼ぶ場合、 それはForを呼ぶことになります。 引数はLisp_Objectでなくてはいけないことを覚えておいてください。 型Lisp_Objectを作るさまざまなマクロと関数は、 ファイル`lisp.h'で宣言されています。

sname

これは、 Lispでの関数を表現するsubrオブジェクトのデータを保持する 構造体に用いるCの変数名です。 この構造体は、 シンボルを生成しsubrオブジェクトを定義に格納する初期化ルーチンに、 Lispシンボル名を渡します。 この名前は 慣例としてfname`F'`S'に置き換えたものとなります。

min

これは、与えられなくてはいけない最小の引数の数です。 関数orの場合、引数のない場合を許しています。

max

これは、固定の最大値があれば、関数が受けつける引数の最大個数です。 または、 引数を評価しないことを示すUNEVALLEDか、 (&restと等価な) 任意個の評価される引数をもつことを示すMANYをもつことになります。 UNEVALLEDMANYは両方ともマクロです。 maxが数の場合、minより小さかったり、 7より大きかったりしてはいけません。

interactive

これは、 Lisp関数のinteractiveへの引数に用いる文字列と 同じ interactive 指示です。 orの場合、これは0(ヌル・ポインタ)で、 orを対話的に呼ぶことはできないことを示します。 値""は、 対話的に呼んだ場合に引数をとらない関数を示します。

doc

これは説明文字列です。 各行末で`\n\'を書かなければならない点を除いて、 Lispで定義する関数の説明文字列と同じように書きます。 特に、1行目は一つの文にしてください。

DEFUNマクロ呼びだしの後で、 すべてのCの関数にあるような引数名リストと、 その後に普通のCの引数宣言を書かなくてはなりません。 引数の最大個数が固定の関数は、 各Lispの引数に対してCの全引数をLisp_Object型として 宣言しなくてはいけません。 Lisp関数に引数の数の上限がないとき、 Cの実装ではちょうど二つの引数を取ります。 1番目がLisp引数の個数で、 2番目が引数の値を格納したブロックのアドレスです。 これらの型はそれぞれintLisp_Object *です。

関数For中で マクロGCPRO1UNGCPROの使い方に 注目してください。 GCPRO1は変数をガベージ・コレクタから保護するのに使います。 これは、 ガベージ・コレクタがこの変数の中を見て、 この内容がアクセス可能なオブジェクトであると みなすようにします。 これはFevalを呼び出す場合や、 Fevalを直接間接に呼び出すもののうちのいずれかを呼び出す場合には 常に必要となります。 このような場合、 (そのような関数の呼出しの後で)再び 参照しようとしているLispオブジェクトも全部保護しなければなりません。 UNGCPROは現在の関数で保護している変数の保護を取消します。 これは陽にそうする必要があります。

ほとんどのデータ型については、 オブジェクトへのポインタを少なくとも一つ保護すれば十分です。 オブジェクトが再利用されるまでは、 そこへのポインタはずっと有効なままです。 ガベージ・コレクタが移動させてしまうので、文字列について、 これはあてはまりません。 ガベージ・コレクタが文字列を移動するとき、 わかる範囲のすべてのポインタのさしかえを行ないますが、 それ以外のポインタは無効になります。 したがって、 ガベージ・コレクションが起こりうる場所以降のすべての 文字列へのポインタを保護しなければなりません。

マクロGCPRO1は局所変数を1個保護します。 2個保護したいときは、 GCPRO2を使います。 GCPRO1を繰り返してもうまくいきません。 なおマクロGCPRO3GCPRO4もあります。

このマクロ群は暗にgcpro1といった局所変数を使います。 これはstruct gcpro型で陽に宣言しなければなりません。 したがって、 GCPRO2を使うときはgcpro1gcpro2を宣言します。 残念ながら、ここでトリッキーな詳細について説明することはできません。

いったんダンプしてしまったEmacsでは、 (いったんEmacsをダンプしたからにはもう書き変えないという場合以外) 静的変数や外部変数でCの初期値を使ってはいけません。 ダンプ後のEmacsで、初期値のある変数は、 (あるオペレーティング・システムで) 読出し専用のメモリ領域に割りつけられるためです。

関数の中では、静的な変数を使ってはいけません。 静的変数はファイルのトップ・レベルに置いてください。 これは、あるオペレーティング・システムにおいて キーワードのstaticを空マクロとして定義するために そうする必要があります (この定義は、初期化の有無にかかわらず、そのようなシステムに おいて静的に宣言した全変数がダンプ後に読出し専用になってしまうために、 使われています)。

Cの関数を定義するだけではLispプリミティブは有効になりません。 プリミティブのLispシンボルを生成し、 関数セルに適切なsubrオブジェクトを格納する必要があります。 これは以下のようなコードになります。

 
defsubr (&subr-structure-name);

ここでsubr-structure-nameDEFUNの第3引数にした (訳注: subrオブジェクトの)変数名です。

すでにLispのプリミティブを定義しているファイルにプリミティブを追加する場合、 (そのファイルの終わり近くにある) syms_of_somethingという名前の関数を探して、 defsubrへの呼出しを追加してください。 ファイルにその関数がない場合や新しくファイルを作る場合、 ファイルにsyms_of_filenameを (たとえば、syms_of_myfileといったふうに) 追加してください。 そして`emacs.c'でこのような関数を呼び出している場所を探し、 syms_of_filenameの呼出しを追加します。

関数syms_of_filenameは、 Lisp変数としても見えるCの変数を定義する場所でもあります。 DEFVAR_LISPは、 Lispから可視なLisp_Object型のC変数を作ります。 DEFVAR_INTは、 Lispでの値が常に整数になるように見えるint型のC変数を作ります。 DEFVAR_BOOLは、 Lispでtnilのどちらかを値に取るように見えるCのint型変数を作ります。

次に、より複雑な引数をもつ別の関数を示します。 これはXウィンドウ・システム用のコードからのもので、 Lispオブジェクトを操作するマクロと関数の使用法を示します。

 
DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
  Scoordinates_in_window_p, 2, 2,
  "xSpecify coordinate pair: \nXExpression which evals to window: ",
  "Return non-nil if POSITIONS is in WINDOW.\n\  
  \(POSITIONS is a list, (SCREEN-X SCREEN-Y)\)\n\
  Returned value is list of positions expressed\n\
  relative to window upper left corner.")
  (coordinate, window)
     register Lisp_Object coordinate, window;
{
  register Lisp_Object xcoord, ycoord;

  if (!CONSP (coordinate)) wrong_type_argument (Qlistp, coordinate);
  CHECK_WINDOW (window, 2);
  xcoord = Fcar (coordinate);
  ycoord = Fcar (Fcdr (coordinate));
  CHECK_NUMBER (xcoord, 0);
  CHECK_NUMBER (ycoord, 1);
  if ((XINT (xcoord) < XINT (XWINDOW (window)->left))
      || (XINT (xcoord) >= (XINT (XWINDOW (window)->left)
                            + XINT (XWINDOW (window)->width))))
    return Qnil;
  XFASTINT (xcoord) -= XFASTINT (XWINDOW (window)->left);
  if (XINT (ycoord) == (screen_height - 1))
    return Qnil;
  if ((XINT (ycoord) < XINT (XWINDOW (window)->top))
      || (XINT (ycoord) >= (XINT (XWINDOW (window)->top)
                            + XINT (XWINDOW (window)->height)) - 1))
    return Qnil;
  XFASTINT (ycoord) -= XFASTINT (XWINDOW (window)->top);
  return (Fcons (xcoord, Fcons (ycoord, Qnil)));
}

Cで定義してある関数以外は、 Cのコードから関数名での呼出しができないことに注意してください。 Lispで書いた関数を呼び出すには、 Lisp関数funcallの本体であるFfuncallを使います。 Lisp関数のfuncallは引数を無制限に受けつけるので、 CではLispレベルでの引数の個数と、 その値を格納した1次元配列の二つの引数を受けつけます。 Lispレベルでの最初の引数は呼び出そうとするLispの関数で、 残りはそれへの引数です。 Ffuncallは評価子を呼び出すことがあるので、 Ffuncallのまわりではポインタを保護する必要があります。

Cの関数call0call1call2などによって、 一定個数の引数でLisp関数を手軽に呼び出すことができます。 これはFfuncallの呼出しによるものです。

例になるものを探すには、`eval.c'は大変適したファイルです。 `lisp.h'には、 いくつか重要なマクロの定義や関数(訳注: の宣言)があります。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

B.5 オブジェクトの内部構造

GNU Emacs Lispは、多くの異なる型を扱います。 実際のデータはヒープに格納され、 プログラムは唯一ポインタを通し、 そのデータに対しアクセスします。 ポインタはほとんどの実装において32ビットの幅をもちます。 オペレーティング・システムと、 Emacsをコンパイルするマシンの型によって、 3ビットにオブジェクトの型を示すタグを用い、 残りの28ビットくらいでオブジェクトを指します (原著では 「オブジェクトを指すのに24ビットから26ビット分ぐらいを用い、 残りの6ビットから8ビットをオブジェクトの型を示すタグとして用います。」 としている)。

Lispオブジェクトに対するアクセスは、 すべてタグのつけられたポインタで表わすため、 どんなオブジェクトであってもオブジェクトのLispデータ型を決めることは 常に可能です。 Cのデータ型Lisp_Objectは、 どんな型のLispオブジェクトでも保持することができます。 普通の変数は、Lisp_Object型なので、 どんなLisp値でもとることができます。 実際のデータ型は実行時に決定できます。 関数引数も同様です。 ある型の引数のみを受け取る関数が必要な場合、 適切な述語を用い、明示的に型の検査を行なう必要があります (see section 型述語)。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

B.5.1 バッファの内部構造

おのおののバッファは、 Lispプログラマが直接アクセスすることのできないフィールドがあります。 ここではCのコードで使う名前でこれらを解説します。 LispプログラムからはLispプリミティブでアクセス可能なフィールドが、 数多くあります。

name

バッファ名は、バッファを名づける文字列です。 これは一意であることが保証されています。See section バッファの名前

save_modified

このフィールドには、 バッファを最後にセーブした時刻を、 整数で格納します。See section バッファの変更

modtime

このフィールドは、読み込んでいるファイルの修正時刻を格納します。 これはそのファイルが書かれるか読まれるかしたときに設定されます。 バッファがファイルに書かれるたびに、 このフィールドは ファイルの修正時刻と比較されます。See section バッファの変更

auto_save_modified

このフィールドは、 バッファが最後に自動セーブされた時刻を格納します。

last_window_start

このフィールドは、 バッファのwindow-start位置、すなわち、 最後にバッファがウィンドウに表示された際、 その表示を開始したバッファ中の位置を格納します。

undo_list

このフィールドは、 バッファのundoリストを指します。See section 取り消し

syntax_table

(原著ではsyntax_table_vとしています) このフィールドは、 バッファに対する構文テーブルを格納します。See section 構文テーブル

downcase_table

このフィールドは、 テキストを小文字に変換するときの変換テーブルを格納します。See section 大文字小文字変換のカスタマイズ

upcase_table

このフィールドは、 テキストを大文字に変換するときの変換テーブルを格納します。See section 大文字小文字変換のカスタマイズ

case_canon_table

このフィールドは、 case-fold検索でテキストを正準化するときの 変換テーブルを格納します。See section 大文字小文字変換のカスタマイズ

case_eqv_table

このフィールドは、 case-fold検索の等価テーブルを格納します。See section 大文字小文字変換のカスタマイズ

display_table

このフィールドは、 バッファの表示テーブルか、 それが存在しない場合は、 nilを格納します。See section 表示テーブル

markers

このフィールドは、 現在、バッファの中を指すすべてのマーカの連鎖を格納します。 バッファのテキストを消去したり バッファのギャップを移動したりした場合には これらの各マーカを検査し、 多分更新をしなくてはいけません。

backed_up

このフィールドは、 このバッファに読み込んでいるファイルのバックアップをとったか否かを示すフラグです。

mark

このフィールドは、 バッファに対するマークを格納します。 マークはマーカですから、 マークはリストmarkersにも含まれます。See section マーク

mark_active

このフィールドは、 バッファのマークがアクティブなら非nilです。

local_var_alist

このフィールドは、バッファ・オブジェクトの特別な場所 (ここでは説明を省きます)に存在するローカル変数以外の、 バッファのローカル変数と、それに対応する値とを含む 連想リストを格納します。See section バッファローカルな変数

base_buffer

このフィールドは、 バッファの基本バッファ (もし間接バッファなら)かnilを保持します。

keymap

このフィールドは、 バッファのローカル・キーマップを保持します。See section キーマップ

overlay_center

このフィールドは、 現在のオーバレイの中央位置を保持します。See section オーバレイ

overlays_before

このフィールドは、 このバッファの現在のオーバレイの中央位置かその前で終わる オーバレイのリストを保持します。 終了位置の逆順で整列してあります。

overlays_after

このフィールドは、 このバッファの現在のオーバレイの中央位置よりも、 後ろで終わるオーバレイのリストを保持します。 先頭位置の昇順に整列してあります。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

B.5.2 ウィンドウの内部構造

ウィンドウは、アクセス可能な以下のフィールドがあります。

frame

ウィンドウのあるフレーム。

mini_p

もしこのウィンドウがミニバッファのウィンドウならば非nil

buffer

ウィンドウが表示しているバッファ。 これはウィンドウの存在期間中に変更されることがしばしばです。

dedicated

もしこのウィンドウがそのバッファ専用ならば非nil

pointm

これは、ウィンドウが選択されている場合、カレント・バッファのポイントです。 選択されていない場合、前の値を保持します。

start

ウィンドウに表示される最初の文字のバッファ中の位置。

force_start

もしこのフラグが非nilならば、 Lispプログラムが陽にウィンドウをスクロールしたことを示します。 ポイントが画面からはずれた場合、 これは次の再表示で何がおきるかに影響します。 ポイントのまわりのテキストを見せるためにウィンドウをスクロールする代わりに、 画面上のある場所にポイントを動かします。

last_modified

最後にウィンドウの再表示を行なったときの、 ウィンドウのバッファのmodifiedフィールド。

last_point

最後にウィンドウの再表示を行なったときの、 ウィンドウのバッファのポイントの値。

left

これは、ウィンドウの左端の桁位置です (画面の左端は桁0です)。

top

これは、ウィンドウの上端の行位置です (画面の上端は行0です)。

height

ウィンドウの高さ(行数)。

width

ウィンドウの幅(桁数)。

next

これは、同胞 (訳注: slibing) の連鎖の中で次に位置するウィンドウです。 同胞のグループで最も右あるいは下のウィンドウでは、nilです。

prev

これは、同胞の連鎖の中で前に位置するウィンドウです。 同胞のグループで最も左あるいは上のウィンドウでは、nilです。

parent

Emacsは内部的にウィンドウの木をもっています。 同胞の各グループには、同胞全部を含んだ親ウィンドウがあります。 このフィールドはその親ウィンドウを指します。

親ウィンドウはバッファの表示をしません。 そして子ウィンドウの形状のほかは、 表示に際した役割をそれほどもおってはいません。 Emacs Lispプログラムでは親ウィンドウにアクセスすることは通常できません。 プログラム上は、実際にバッファを表示する、 木の葉にあたるウィンドウだけを操作します。

hscroll

これは、 ウィンドウ中の表示が水平方向に左にスクロールされるときの桁数です。 通常は0です。

use_time

これは、ウィンドウが最後に選択された時刻です。 このフィールドはget-lru-windowで用いられます。

display_table

ウィンドウの表示テーブルか、 もしそれがなければnil

update_mode_line

nilはウィンドウのモード行の更新が必要なことを意味します。

base_line_number

バッファ上のある位置の行番号またはnil。 これはモード行にポイントの行番号を表示するときに使います。

base_line_pos

行番号のわかっているバッファ上の位置、あるいは不明な場合はnil

region_showing

もしこのウィンドウでリージョン(かその一部分)が強調表示しているなら、 このフィールドはリージョンの一端となるマークの位置。 さもなくばこのフィールドはnil


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

B.5.3 プロセスの内部構造

プロセスのフィールドは、以下のとおり。

name

プロセスの名前の文字列。

command

プロセスを始動したときのコマンド引数を格納するリスト。

filter

バッファのかわりに、 プロセスからの出力を受け取るのに用いられる関数。

sentinel

プロセスがシグナルを受け取ったときに呼ばれる関数か、nil

buffer

プロセスに対応したバッファ。

pid

プロセスのUnixプロセスIDの整数。

childp

フラグで、本当の子プロセスなら非nil。 ネットワーク接続ならnil

mark

このプロセスからバッファに挿入された最後の出力の終りを設定するマーカ。 バッファの最後であることがしばしばですが、常にそうではありません。

kill_without_query

もし非nilならば、 このプロセスの実行中にEmacsが死ぬ際、 このプロセスを殺す前の確認をとらないことを意味します。

raw_status_low
raw_status_high

この二つのフィールドは、 waitシステムコールが返したプロセス状態を、 16ビットずつ記録しています。

status

process-statusが返すべきプロセス状態。

tick
update_tick

もしこれら二つのフィールドが等しくないなら、 見張りを実行するかプロセスバッファにメッセージを挿入するかして プロセス状態の変更が必要であることを示します。

pty_flag

もしサブプロセスとの通信にPTYを使うなら非nil、 もしパイプを使うのならnil

infd

プロセスからの入力ファイル記述子。

outfd

プロセスへの出力ファイル記述子。

subtty

子プロセスが使う端末のファイル記述子 (システムによっては記録する必要がないので、値はnilです)。

tty_name

サブプロセスの使っている端末の名前か、または、 パイプを使っている場合はnil


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Yasutaka SHINDOH on September, 29 2006 using texi2html 1.76.