今日の関数 searchit その1 (https://github.com/vim/vim)

search.c

int
searchit(
    win_T	*win,		/* window to search in; can be NULL for a
				   buffer without a window! */
    buf_T	*buf,
    pos_T	*pos,
    int		dir,
    char_u	*pat,
    long	count,
    int		options,
    int		pat_use,	/* which pattern to use when "pat" is empty */
    linenr_T	stop_lnum,	/* stop after this line number when != 0 */
    proftime_T	*tm UNUSED)	/* timeout limit or NULL */
{

0以外が返ればなら検索成功となります。

search.c

 
...

if (search_regcomp(pat, RE_SEARCH, pat_use,
			(options & (SEARCH_HIS + SEARCH_KEEP)), &regmatch) == FAIL)
{
	if ((options & SEARCH_MSG) && !rc_did_emsg)
		EMSG2(_("E383: Invalid search string: %s"), mr_pattern);
	return FAIL;
}

検索パターンのエラーチェックをします。

search.c

do	/* loop for count */
{
	
	...
	 

無限ループに入ります。

search.c

			if (pos->col == MAXCOL)
				start_char_len = 0;
#ifdef FEAT_MBYTE
			/* Watch out for the "col" being MAXCOL - 2, used in a closed fold. */
			 
			//------------------------------
			// pos ga max - 2 ika nara
			//------------------------------

			else if (has_mbyte
					&& pos->lnum >= 1 && pos->lnum <= buf->b_ml.ml_line_count
					&& pos->col < MAXCOL - 2)
			{
				 
				//------------------------------
				// ptr = buf + col
				//------------------------------

				ptr = ml_get_buf(buf, pos->lnum, FALSE) + pos->col;
				if (*ptr == NUL)
					start_char_len = 1;
				else
					start_char_len = (*mb_ptr2len)(ptr);
			}
#endif
			else
				start_char_len = 1;
			 

今のカーソル位置でstart_char_lenを設定していきます。
カーソル位置がMAXCOLにないかmultibyteの時カーソル位置の文字がNULでないならstart_char_lenは1となります。
このstart_char_lenはextra_colに入れられSEARCH_START(カーソルの位置を検索に含める)オプションのために使われます。

search.c

if (dir == FORWARD)
{
	if (options & SEARCH_START)
		extra_col = 0;
	else
		extra_col = start_char_len;
}
else
{
	if (options & SEARCH_START)
		extra_col = start_char_len;
	else
		extra_col = 0;
}

SEARCH_START(カーソルの位置を検索に含める)オプションがついているなら
検索の方向によってextra_colが0か1に設定されます。
前方検索ならSEARCH_STARTがあるならextra_colに1が入りカーソル位置の文字を飛ばします。
SEARCH_STARTがないならextra_colは0で検索はカーソル位置の文字から始まります。

search.c

start_pos = *pos;	/* remember start pos for detecting no match */
found = 0;		/* default: not found */
at_first_line = TRUE;	/* default: start in first line */
 
if (pos->lnum == 0)	/* correct lnum for when starting in line 0 */
{
	pos->lnum = 1;
	pos->col = 0;
	at_first_line = FALSE;  /* not in first line now */
}


検索ループに入る前の変数の初期化です。

search.c

//------------------------------
// imano gyou no search
// moshi back de col ga 0 de nainara
//------------------------------

if (dir == BACKWARD && start_pos.col == 0
		&& (options & SEARCH_START) == 0)
{
	lnum = pos->lnum - 1;
	at_first_line = FALSE;
}
else
	lnum = pos->lnum;

lnum(行数)は今のカーソル位置のlnumをとります。
ただ後方検索の時で今のカーソル位置が0でしかもカーソル位置の文字を含めるオプションがついていない時は
lnumをカーソル位置の行の一つ前の行を入れます。そしてat_first_lineにFALSEを入れています。

search.c

for (loop = 0; loop <= 1; ++loop)   /* loop twice if 'wrapscan' set */
{
	 
	for ( ; lnum > 0 && lnum <= buf->b_ml.ml_line_count; lnum += dir, at_first_line = FALSE) // dir ha 1 ka -1
	{
		...
	

wrapscanは検索が最後まで行ったらまた最初からもう一度
検索するオプションです。そのために2回ループするようになっています。
その中にもう一つ行を舐めていくループがあります。
lnumが0以上でbufferの行数以下でループが回ります。
dirは前方で1後方検索で-1なのでどちらの方向でもこのループは機能します。

search.c

	if (stop_lnum != 0 && (dir == FORWARD ? lnum > stop_lnum : lnum < stop_lnum))
			break;
		 
#ifdef FEAT_RELTIME
		/* Stop after passing the "tm" time limit. */
	if (tm != NULL && profile_passed_limit(tm))
			break;
#endif

stop_lnumとタイムリミットがセットされているならチェックします。

search.c

col = at_first_line && (options & SEARCH_COL) ? pos->col : (colnr_T)0;

colの設定をします。at_first_lineがTRUEでカーソル位置の文字を含めるオプションがあるなら
そのままカーソル位置のcolを入れます。
そうでなければ0です。一番最初の行にいる時だけカーソル位置を指定しています。