[emacs] emacsのソースを読む (eval.c)

現在emacsのソースを読んで、解析内容をwikiにめもってます。

例えばDEFUN解析。このマクロはやったら出てくるのでとりあえずどんな風になってるか調べてみました。

例としてorを出します

ここで注意するのは、(args) Lisp_Object args = (args Lisp_Object args)であるということを念頭においてソースを読むということ

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;

DEFUNは次のように定義されています

#define DEFUN(lname, fnname, sname, minargs, maxargs, prompt, doc)  \
  Lisp_Object fnname ();            \  //関数定義
  struct Lisp_Subr sname =            \ //要素代入
    { PVEC_SUBR | (sizeof (struct Lisp_Subr) / sizeof (EMACS_INT)), \
      fnname, minargs, maxargs, lname, prompt, 0};      \
  Lisp_Object fnname          //関数の実装

マクロの内容はコメントのとおりです。最後の関数の実装というのは、マクロ展開した後に秘密があるのでこういう内容になりました。

つぎにLisp_Subr これがどうなっているか分からないとDEFUNがどうなっているかも分からないのでみてみる事にします。built in structure

struct Lisp_Subr
  {
    EMACS_INT size;
    Lisp_Object (*function) ();
    short min_args, max_args;
    char *symbol_name;
    char *prompt;
    char *doc;
  };

以上の3つの構造および、Lisp_Object がint もしくは long(64bitだとlong)という事を知っておけばDEFUNの解析は終了する。

例として、orのDEFUN定義においてマクロ展開される内容について検討してみる。  マクロ展開はcppとか使うと便利かも

Lisp_Object for(); 
struct Lisp_Subr Sor =
  {
    EMACS_INT size  =  PVEC_SUBR | (sizeof (struct Lisp_Subr) / sizeof (EMACS_INT));
    Lisp_Object (*function) () = For ;
    short min_args = 0;
    short max_args = UNEVALLED;
    char *symbol_name = "or";
    char *prompt = 0;
    char *doc = "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." ;
  };
Lisp_Object fnname for  (args)
     Lisp_Object args;

こんな感じになります。結構分かりやすいですね

ちなみにSorは

defsubr (&Sor);

という感じで登録されます。

まぁもっと詳しい事を知りたければwikiでも見てください。もうちょっと詳しく解析してます

emacsの色々と調べることが多くてめんどうですがそこそこ面白くもあります。飽きない程度に解析するつもり。飽きたらapacheとかasteriskとかmysqlとかみていく予定


おまけ: emacsのメインの流れ

main⇒init処理とかsignal処理⇒recursive_edit⇒recursive_edit_1⇒command_loop てな感じになってます。はい、たぶんw(ノ∀`)  recursive_editってなんだろか

おまけ2: keyboard登録

これを変更(もしくは追加)すれば自分の思いのままのキー設定をデフォルトで使えるようになる。(まぁそんなことする必要ないかもしれないけど)

void
keys_of_keyboard ()
{
  initial_define_key (global_map, Ctl ('Z'), "suspend-emacs");
  initial_define_key (control_x_map, Ctl ('Z'), "suspend-emacs");
  initial_define_key (meta_map, Ctl ('C'), "exit-recursive-edit");
  initial_define_key (global_map, Ctl (']'), "abort-recursive-edit");
  initial_define_key (meta_map, 'x', "execute-extended-command");

  initial_define_lispy_key (Vspecial_event_map, "delete-frame",
          "handle-delete-frame");
  initial_define_lispy_key (Vspecial_event_map, "iconify-frame",
          "ignore-event");
  initial_define_lispy_key (Vspecial_event_map, "make-frame-visible",
          "ignore-event");
}

initial_define_keyでキー設定をしてるのが分かる。