regex.c:3149
int
re_search(bufp, string, size, startpos, range, regs)
     struct re_pattern_buffer *bufp;
     const char *string;
     int size, startpos, range;
     struct re_registers *regs;
{
  register char *fastmap = bufp->fastmap;
  int val, anchor = 0, initpos = startpos;

  /* Check for out-of-range starting position.  */
  if (startpos < 0  ||  startpos > size)
    return -1;

  /* Update the fastmap now if not correct already.  */
  if (fastmap && !bufp->fastmap_accurate) {
    re_compile_fastmap(bufp);
  }


  /* If the search isn't to be a backwards one, don't waste time in a
     search for a pattern that must be anchored.  */
  if (bufp->used > 0) {
    switch ((enum regexpcode)bufp->buffer[0]) {
    case begbuf:
    begbuf_match:
      if (range > 0) {
	if (startpos > 0) return -1;
	else {
	  val = re_match(bufp, string, size, 0, regs);
	  if (val >= 0) return 0;
	  return val;
	}
      }
      break;

    case begline:
      anchor = 1;
      break;

    case begpos:
      val = re_match(bufp, string, size, startpos, regs);
      if (val >= 0) return startpos;
      return val;

    default:
      break;
    }
  }
  if (bufp->options & RE_OPTIMIZE_ANCHOR) {
    if (bufp->options&RE_OPTION_MULTILINE && range > 0) {
      goto begbuf_match;
    }
    anchor = 1;
  }

  if (bufp->must) {
    int len = ((unsigned char*)bufp->must)[0];
    int pos, pbeg, pend;

    pbeg = startpos;
    pend = startpos + range;
    if (pbeg > pend) {		/* swap pbeg,pend */
      pos = pend; pend = pbeg; pbeg = pos;
    }
    pend = size;
    if (bufp->options & RE_OPTIMIZE_NO_BM) {
      pos = slow_search(bufp->must+1, len,
			string+pbeg, pend-pbeg,
			MAY_TRANSLATE()?translate:0);
    }
    else {
      pos = bm_search(bufp->must+1, len,
		      string+pbeg, pend-pbeg,
		      bufp->must_skip,
		      MAY_TRANSLATE()?translate:0);
    }
    if (pos == -1) return -1;
    if (range > 0 && (bufp->options & RE_OPTIMIZE_EXACTN)) {
      startpos += pos;
      range -= pos;
      if (range < 0) return -1;
    }
  }

  for (;;) {
    /* If a fastmap is supplied, skip quickly over characters that
       cannot possibly be the start of a match.  Note, however, that
       if the pattern can possibly match the null string, we must
       test it at each starting point so that we take the first null
       string we get.  */

    if (fastmap && startpos < size
	&& bufp->can_be_null != 1 && !(anchor && startpos == 0)) {
      if (range > 0) {	/* Searching forwards.  */
	register unsigned char *p, c;
	int irange = range;

	p = (unsigned char*)string+startpos;

	while (range > 0) {
	  c = *p++;
	  if (ismbchar(c)) {
	    int len;

	    if (fastmap[c])
	      break;
	    len = mbclen(c) - 1;
	    while (len--) {
	      c = *p++;
	      range--;
	      if (fastmap[c] == 2)
		goto startpos_adjust;
	    }
	  }
	  else {
	    if (fastmap[MAY_TRANSLATE() ? translate[c] : c])
	      break;
	  }
	  range--;
	}
      startpos_adjust:
	startpos += irange - range;
      }
      else {			/* Searching backwards.  */
	register unsigned char c;

	c = string[startpos];
	c &= 0xff;
	if (MAY_TRANSLATE() ? !fastmap[translate[c]] : !fastmap[c])
	  goto advance;
      }
    }

    if (startpos > size) return -1;
    if ((anchor || !bufp->can_be_null) && range > 0 && size > 0 && startpos == size)
      return -1;
    val = re_match_exec(bufp, string, size, startpos, initpos, regs);
    if (val >= 0) return startpos;
    if (val == -2) return -2;

#ifndef NO_ALLOCA
#ifdef C_ALLOCA
    alloca(0);
#endif /* C_ALLOCA */
#endif /* NO_ALLOCA */

    if (range > 0) {
      if (anchor && startpos < size &&
	  (startpos < 1 || string[startpos-1] != '\n')) {
	while (range > 0 && string[startpos] != '\n') {
	  range--;
	  startpos++;
	}
      }
    }

  advance:
    if (!range) 
      break;
    else if (range > 0) {
      const char *d = string + startpos;

      if (ismbchar(*d)) {
	int len = mbclen(*d) - 1;
	range-=len, startpos+=len;
	if (!range)
	  break;
      }
      range--, startpos++;
    }
    else {
      range++, startpos--;
      {
	const char *s, *d, *p;

	s = string; d = string + startpos;
	for (p = d; p-- > s && ismbchar(*p); )
	  /* --p >= s would not work on 80[12]?86. 
	     (when the offset of s equals 0 other than huge model.)  */
	  ;
	if (!((d - p) & 1)) {
	  if (!range)
	    break;
	  range++, startpos--;
	}
      }
    }
  }
  return -1;
}
