vimのソースを読んでみるテスト(その2 黄昏の秋)

始めにREADME.txtを読んだのでこれからは具体的にソースを見ていこうと思います

ちなみにvimのコーディングはかなり古いスタイルをとってます。C++じゃあ使えません.. とある団体にはたぶん怒られるような書き方をしてます。

とりあえずmain.cから眺めてみるテスト。main.cを見るといきなり次のようなデータ構造が出現する

とりあえず最重要データ構造とみてよさげ。 構造体の中に,argcとかargvとか入ってるってのが面白い。長いのでとりあえず処理を追いつつ見ていくつもり

/* Struct for various parameters passed between main() and other functions. */
typedef struct
{
int argc;
char **argv;

int evim_mode; /* started as "evim" */
char_u *use_vimrc; /* vimrc from -u argument */

int n_commands; /* no. of commands from + or -c */
char_u *commands[MAX_ARG_CMDS]; /* commands from + or -c arg. */
char_u cmds_tofree[MAX_ARG_CMDS]; /* commands that need free() */
int n_pre_commands; /* no. of commands from --cmd */
char_u *pre_commands[MAX_ARG_CMDS]; /* commands from --cmd argument */

int edit_type; /* type of editing to do */
char_u *tagname; /* tag from -t argument */
#ifdef FEAT_QUICKFIX
char_u *use_ef; /* 'errorfile' from -q argument */
#endif

int want_full_screen;
int stdout_isatty; /* is stdout a terminal? */
char_u *term; /* specified terminal name */
#ifdef FEAT_CRYPT
int ask_for_key; /* -x argument */
#endif
int no_swap_file; /* "-n" argument used */
#ifdef FEAT_EVAL
int use_debug_break_level;
#endif
#ifdef FEAT_WINDOWS
int window_count; /* number of windows to use */
int window_layout; /* 0, WIN_HOR, WIN_VER or WIN_TABS */
#endif

#ifdef FEAT_CLIENTSERVER
int serverArg; /* TRUE when argument for a server */
char_u *serverName_arg; /* cmdline arg for server name */
char_u *serverStr; /* remote server command */
char_u *serverStrEnc; /* encoding of serverStr */
char_u *servername; /* allocated name for our server */
#endif
#if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE)
int literal; /* don't expand file names */
#endif
#ifdef MSWIN
int full_path; /* file name argument was full path */
#endif
#ifdef FEAT_DIFF
int diff_mode; /* start with 'diff' set */
#endif
} mparm_T;

そしてedit_typeを定義しだす。クイックフィックスモードってのが謎である。

/* Values for edit_type. */
#define EDIT_NONE 0 /* no edit type yet */
#define EDIT_FILE 1 /* file name argument[s] given, use argument list */
#define EDIT_STDIN 2 /* read file from stdin */
#define EDIT_TAG 3 /* tag name argument given, use tagname */
#define EDIT_QF 4 /* start in quickfix mode */

そして物語の始まりというわけでメイン処理が始まっていきます

条件処理が何かと面倒なことになってるのはおいておきたい。まさか始めに、_cdeclとか出てくるとは思わなかった。_cdeclっちゅーのはスタックとかと関係してあれやこれやっていうやつで、_stdcallってのもスタックに関連して存在します。 詳しく突っ込んで調べたいとは思いますが、ページの都合上とばしてみる。(ぇー

#ifndef PROTO /* don't want a prototype for main() */
int
# ifdef VIMDLL
_export
# endif
# ifdef FEAT_GUI_MSWIN
# ifdef __BORLANDC__
_cdecl
# endif
VimMain
# else
main
# endif
(argc, argv)
int argc;
char **argv;
{

で、次に以下のコードが出てきます

char_uってのはunsigned charのこと。ucharとかでdefineしてるのはよく見かける。char_uは初めてかも知れない

char_u *fname = NULL; /* file name from command line */
mparm_T params; /* various parameters passed between
* main() and other functions. */

でsignalの設定とかviminfoの読みこみなど、あれこれやって最後に以下のコマンドがきます

これを実行し、main_loopの処理が永遠と繰り返されることになります

* Call the main command loop. This never returns.
*/
main_loop(FALSE, FALSE);

return 0;
}


で次に何故かedit()関数を見てみることにします。edit()はインサートモードが始まった時に呼び出されます。定義は以下のようになっております

始めにあれやこれやと説明が書いてあります

/*
* edit(): Start inserting text.
*
* "cmdchar" can be:
* 'i' normal insert command
* 'a' normal append command
* 'R' replace command
* 'r' "r" command: insert one . Note: count can be > 1, for redo,
* but still only one is inserted. The is not used for redo.
* 'g' "gI" command.
* 'V' "gR" command for Virtual Replace mode.
* 'v' "gr" command for single character Virtual Replace mode.
*
* This function is not called recursively. For CTRL-O commands, it returns
* and lets the caller handle the Normal-mode command.
*
* Return TRUE if a CTRL-O command caused the return (insert mode pending).
*/
int
edit(cmdchar, startln, count)
int cmdchar;
int startln; /* if set, insert at start of line */
long count;
{

editのソースを読んでるうちにrestart_editというのがたくさんでてきたのでしらべたところinsertモード中Ctrl+oを実行すると一時インサートモード?(xとか実行すると文字が消せる)ということができるということがわかった。詳しい用途は不明...

ちなみにvim実行時、左下に出てくるINSERTとかいう文字列はSTATEグローバル変数として定義されています。コマンドを実行する際にSTETE=NORMALなどとして変更して表示を変更させるようになっているようです