⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 regexp.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:
		else if (OP(next) >= BRACE_COMPLEX &&
			 OP(next) < BRACE_COMPLEX + 10)
		{
		    no = OP(next) - BRACE_COMPLEX;
		    brace_min[no] = OPERAND_MIN(scan);
		    brace_max[no] = OPERAND_MAX(scan);
		    brace_count[no] = 0;
		}
		else
		{
		    emsg(e_internal);	    /* Shouldn't happen */
		    return 0;
		}
	    }
	    break;
	  case BRACE_COMPLEX + 0:
	  case BRACE_COMPLEX + 1:
	  case BRACE_COMPLEX + 2:
	  case BRACE_COMPLEX + 3:
	  case BRACE_COMPLEX + 4:
	  case BRACE_COMPLEX + 5:
	  case BRACE_COMPLEX + 6:
	  case BRACE_COMPLEX + 7:
	  case BRACE_COMPLEX + 8:
	  case BRACE_COMPLEX + 9:
	    {
		int	    no;
		char_u	    *save;

		no = OP(scan) - BRACE_COMPLEX;
		++brace_count[no];

		/* If not matched enough times yet, try one more */
		if (brace_count[no] <= (brace_min[no] <= brace_max[no]
				    ? brace_min[no] : brace_max[no]))
		{
		    save = reginput;
		    if (regmatch(OPERAND(scan)))
			return 1;
		    reginput = save;
		    --brace_count[no];	/* failed, decrement match count */
		    return 0;
		}

		/* If matched enough times, may try matching some more */
		if (brace_min[no] <= brace_max[no])
		{
		    /* Range is the normal way around, use longest match */
		    if (brace_count[no] <= brace_max[no])
		    {
			save = reginput;
			if (regmatch(OPERAND(scan)))
			    return 1;	    /* matched some more times */
			reginput = save;
			--brace_count[no];  /* matched just enough times */
			/* continue with the items after \{} */
		    }
		}
		else
		{
		    /* Range is backwards, use shortest match first */
		    if (brace_count[no] <= brace_min[no])
		    {
			save = reginput;
			if (regmatch(next))
			    return 1;
			reginput = save;
			next = OPERAND(scan);
			/* must try to match one more item */
		    }
		}
	    }
	    break;

	  case BRACE_SIMPLE:
	  case STAR:
	  case PLUS:
	    {
		int	nextch;
		int	nextch_ic;
		int	no;
		char_u	*save;

		/*
		 * Lookahead to avoid useless match attempts when we know
		 * what character comes next.
		 */
		if (OP(next) == EXACTLY)
		{
		    nextch = *OPERAND(next);
		    if (reg_ic)
		    {
			if (isupper(nextch))
			    nextch_ic = TO_LOWER(nextch);
			else
			    nextch_ic = TO_UPPER(nextch);
		    }
		    else
			nextch_ic = nextch;
		}
		else
		{
		    nextch = '\0';
		    nextch_ic = '\0';
		}
		if (OP(scan) != BRACE_SIMPLE)
		{
		    minval = (OP(scan) == STAR) ? 0 : 1;
		    maxval = MAX_LIMIT;
		}

		save = reginput;
		no = regrepeat(OPERAND(scan));
		if (minval <= maxval)
		{
		    /* Range is the normal way around, use longest match */
		    if (no > maxval)
		    {
			no = maxval;
			reginput = save + no;
		    }
		    while (no >= minval)
		    {
			/* If it could work, try it. */
			if (nextch == '\0' || *reginput == nextch
						    || *reginput == nextch_ic)
			    if (regmatch(next))
				return 1;
			/* Couldn't or didn't -- back up. */
			no--;
			reginput = save + no;
		    }
		}
		else
		{
		    /* Range is backwards, use shortest match first */
		    if (no < maxval)
			return 0;
		    if (minval > no)
			minval = no;	/* Actually maximum value */
		    no = maxval;
		    reginput = save + no;
		    while (no <= minval)
		    {
			/* If it could work, try it. */
			if (nextch == '\0' || *reginput == nextch
						    || *reginput == nextch_ic)
			    if (regmatch(next))
				return 1;
			/* Couldn't or didn't -- try longer match. */
			no++;
			reginput = save + no;
		    }
		}
		return 0;
	    }
	    /* break; Not Reached */
	  case END:
	    return 1;	    /* Success! */
	    /* break; Not Reached */
	  default:
	    emsg(e_re_corr);
#ifdef DEBUG
	    printf("Illegal op code %d\n", OP(scan));
#endif
	    return 0;
	    /* break; Not Reached */
	}

	scan = next;
    }

    /*
     * We get here only if there's trouble -- normally "case END" is the
     * terminating point.
     */
    emsg(e_re_corr);
#ifdef DEBUG
    printf("Premature EOL\n");
#endif
    return 0;
}

/*
 * regrepeat - repeatedly match something simple, report how many
 */
    static int
regrepeat(p)
    char_u	*p;
{
    int		count = 0;
    char_u	*scan;
    char_u	*opnd;
    int		mask;

    scan = reginput;
    opnd = OPERAND(p);
    switch (OP(p))
    {
      case ANY:
	count = STRLEN(scan);
	scan += count;
	break;
      case IDENT:
	for (count = 0; vim_isIDc(*scan); ++count)
	    ++scan;
	break;
      case KWORD:
	for (count = 0; vim_iswordc(*scan); ++count)
	    ++scan;
	break;
      case FNAME:
	for (count = 0; vim_isfilec(*scan); ++count)
	    ++scan;
	break;
      case PRINT:
	for (count = 0; charsize(*scan) == 1; ++count)
	    ++scan;
	break;
      case SIDENT:
	for (count = 0; !isdigit(*scan) && vim_isIDc(*scan); ++count)
	    ++scan;
	break;
      case SWORD:
	for (count = 0; !isdigit(*scan) && vim_iswordc(*scan); ++count)
	    ++scan;
	break;
      case SFNAME:
	for (count = 0; !isdigit(*scan) && vim_isfilec(*scan); ++count)
	    ++scan;
	break;
      case SPRINT:
	for (count = 0; !isdigit(*scan) && charsize(*scan) == 1; ++count)
	    ++scan;
	break;
      case WHITE:
	for (count = 0; vim_iswhite(*scan); ++count)
	    ++scan;
	break;
      case NWHITE:
	for (count = 0; *scan != NUL && !vim_iswhite(*scan); ++count)
	    ++scan;
	break;
      case DIGIT:
	mask = RI_DIGIT;
do_class:
	for (count = 0; class_tab[*scan] & mask; ++count)
	    ++scan;
	break;
      case NDIGIT:
	mask = RI_DIGIT;
do_nclass:
	for (count = 0; *scan != NUL && !(class_tab[*scan] & mask); ++count)
	    ++scan;
	break;
      case HEX:
	mask = RI_HEX;
	goto do_class;
      case NHEX:
	mask = RI_HEX;
	goto do_nclass;
      case OCTAL:
	mask = RI_OCTAL;
	goto do_class;
      case NOCTAL:
	mask = RI_OCTAL;
	goto do_nclass;
      case WORD:
	mask = RI_WORD;
	goto do_class;
      case NWORD:
	mask = RI_WORD;
	goto do_nclass;
      case HEAD:
	mask = RI_HEAD;
	goto do_class;
      case NHEAD:
	mask = RI_HEAD;
	goto do_nclass;
      case ALPHA:
	mask = RI_ALPHA;
	goto do_class;
      case NALPHA:
	mask = RI_ALPHA;
	goto do_nclass;
      case LOWER:
	mask = RI_LOWER;
	goto do_class;
      case NLOWER:
	mask = RI_LOWER;
	goto do_nclass;
      case UPPER:
	mask = RI_UPPER;
	goto do_class;
      case NUPPER:
	mask = RI_UPPER;
	goto do_nclass;
      case EXACTLY:
	{
	    int	    cu, cl;

	    if (reg_ic)
	    {
		cu = TO_UPPER(*opnd);
		cl = TO_LOWER(*opnd);
		while (*scan == cu || *scan == cl)
		{
		    count++;
		    scan++;
		}
	    }
	    else
	    {
		cu = *opnd;
		while (*scan == cu)
		{
		    count++;
		    scan++;
		}
	    }
	    break;
	}
      case ANYOF:
	while (*scan != '\0' && cstrchr(opnd, *scan) != NULL)
	{
	    count++;
	    scan++;
	}
	break;
      case ANYBUT:
	while (*scan != '\0' && cstrchr(opnd, *scan) == NULL)
	{
	    count++;
	    scan++;
	}
	break;
      default:			/* Oh dear.  Called inappropriately. */
	emsg(e_re_corr);
#ifdef DEBUG
	printf("Called regrepeat with op code %d\n", OP(p));
#endif
	count = 0;		/* Best compromise. */
	break;
    }
    reginput = scan;

    return count;
}

/*
 * regnext - dig the "next" pointer out of a node
 */
    static char_u *
regnext(p)
    char_u  *p;
{
    int	    offset;

    if (p == JUST_CALC_SIZE)
	return NULL;

    offset = NEXT(p);
    if (offset == 0)
	return NULL;

    if (OP(p) == BACK)
	return p - offset;
    else
	return p + offset;
}

#ifdef DEBUG

/*
 * regdump - dump a regexp onto stdout in vaguely comprehensible form
 */
    static void
regdump(pattern, r)
    char_u	*pattern;
    vim_regexp	*r;
{
    char_u  *s;
    int	    op = EXACTLY;	/* Arbitrary non-END op. */
    char_u  *next;

    printf("\nregcomp(%s):\n", pattern);

    s = r->program + 1;
    while (op != END)		/* While that wasn't END last time... */
    {
	op = OP(s);
	printf("%2d%s", (int)(s - r->program), regprop(s)); /* Where, what. */
	next = regnext(s);
	if (next == NULL)	/* Next ptr. */
	    printf("(0)");
	else
	    printf("(%d)", (int)((s - r->program) + (next - s)));
	if (op == BRACE_LIMITS)
	{
	    /* Two short ints */
	    printf(" minval %d, maxval %d", OPERAND_MIN(s), OPERAND_MAX(s));
	    s += 4;
	}
	s += 3;
	if (op == ANYOF || op == ANYBUT || op == EXACTLY)
	{
	    /* Literal string, where present. */
	    while (*s != '\0')
		printf("%c", *s++);
	    s++;
	}
	printf("\n");
    }

    /* Header fields of interest. */
    if (r->regstart != '\0')
	printf("start `%c' ", r->regstart);
    if (r->reganch)
	printf("anchored ");
    if (r->regmust != NULL)
	printf("must have \"%s\"", r->regmust);
    printf("\n");
}

/*
 * regprop - printable representation of opcode
 */
    static char_u *
regprop(op)
    char_u	   *op;
{
    char_u	    *p;
    static char_u   buf[50];

    (void) strcpy(buf, ":");

    switch (OP(op))
    {
      case BOL:
	p = "BOL";
	break;
      case EOL:
	p = "EOL";
	break;
      case BOW:
	p = "BOW";
	break;
      case EOW:
	p = "EOW";
	break;
      case ANY:
	p = "ANY";
	break;
      case IDENT:
	p = "IDENT";
	break;
      case KWORD:
	p = "KWORD";
	break;
      case FNAME:
	p = "FNAME";
	break;
      case PRINT:
	p = "PRINT";
	break;
      case SIDENT:
	p = "SIDENT";
	break;
      case SWORD:
	p = "SWORD";
	break;
      case SFNAME:
	p = "SFNAME";
	break;
      case SPRINT:
	p = "SPRINT";
	break;
      case WHITE:
	p = "WHITE";
	break;
      case NWHITE:
	p = "NWHITE";
	break;
      case DIGIT:
	p = "DIGIT";
	break;
      case NDIGIT:
	p = "NDIGIT";
	break;
      case HEX:
	p = "HEX";
	break;
      case NHEX:
	p = "NHEX";
	break;
      case OCTAL:
	p = "OCTAL";
	break;
      case NOCTAL:
	p = "NOCTAL";
	break;
      case WORD:
	p = "WORD";
	break;
      case NWORD:
	p = "NWORD";
	break;
      case HEAD:
	p = "HEAD";
	break;
      case NHEAD:
	p = "NHEAD";
	break;
      case ALPHA:
	p = "ALPHA";
	break;
      case NALPHA:
	p = "NALPHA";
	break;
      case LOWER:
	p = "LOWER";
	break;
      case NLOWER:
	p = "NLOWER";
	break;
      case UPPER:
	p = "UPPER";
	break;
      case

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -