(byte_re_match_2_internal): For gcc replace switch statement with gotos.

This commit is contained in:
Ulrich Drepper 2001-11-17 12:03:29 +00:00
parent c83a3aeb8f
commit 618c17e387

View File

@ -5814,6 +5814,88 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
unsigned num_regs_pushed = 0; unsigned num_regs_pushed = 0;
#endif #endif
/* Definitions for state transitions. More efficiently for gcc. */
#ifdef __GNUC__
# if defined HAVE_SUBTRACT_LOCAL_LABELS && defined SHARED
# define NEXT \
do \
{ \
int offset; \
const void *__unbounded ptr; \
offset = (p == pend \
? 0 : jmptable[SWITCH_ENUM_CAST ((re_opcode_t) *p++)]); \
ptr = &&end_of_pattern + offset; \
goto *ptr; \
} \
while (0)
# define REF(x) \
&&label_##x - &&end_of_pattern
# define JUMP_TABLE_TYPE const int
# else
# define NEXT \
do \
{ \
const void *__unbounded ptr; \
ptr = (p == pend ? &&end_of_pattern \
: jmptable[SWITCH_ENUM_CAST ((re_opcode_t) *p++)]); \
goto *ptr; \
} \
while (0)
# define REF(x) \
&&label_##x
# define JUMP_TABLE_TYPE const void *const
# endif
# define CASE(x) label_##x
static JUMP_TABLE_TYPE jmptable[] =
{
REF (no_op),
REF (succeed),
REF (exactn),
# ifdef MBS_SUPPORT
REF (exactn_bin),
# endif
REF (anychar),
REF (charset),
REF (charset_not),
REF (start_memory),
REF (stop_memory),
REF (duplicate),
REF (begline),
REF (endline),
REF (begbuf),
REF (endbuf),
REF (jump),
REF (jump_past_alt),
REF (on_failure_jump),
REF (on_failure_keep_string_jump),
REF (pop_failure_jump),
REF (maybe_pop_jump),
REF (dummy_failure_jump),
REF (push_dummy_failure),
REF (succeed_n),
REF (jump_n),
REF (set_number_at),
REF (wordchar),
REF (notwordchar),
REF (wordbeg),
REF (wordend),
REF (wordbound),
REF (notwordbound)
# ifdef emacs
,REF (before_dot),
REF (at_dot),
REF (after_dot),
REF (syntaxspec),
REF (notsyntaxspec)
# endif
};
#else
# define NEXT \
break
# define CASE(x) \
case x
#endif
DEBUG_PRINT1 ("\n\nEntering re_match_2.\n"); DEBUG_PRINT1 ("\n\nEntering re_match_2.\n");
INIT_FAIL_STACK (); INIT_FAIL_STACK ();
@ -6036,13 +6118,21 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
DEBUG_PRINT2 ("\n0x%x: ", p); DEBUG_PRINT2 ("\n0x%x: ", p);
#endif #endif
#ifdef __GNUC__
NEXT;
#else
if (p == pend) if (p == pend)
{ /* End of pattern means we might have succeeded. */ #endif
DEBUG_PRINT1 ("end of pattern ... "); {
#ifdef __GNUC__
end_of_pattern:
#endif
/* End of pattern means we might have succeeded. */
DEBUG_PRINT1 ("end of pattern ... ");
/* If we haven't matched the entire string, and we want the /* If we haven't matched the entire string, and we want the
longest match, try backtracking. */ longest match, try backtracking. */
if (d != end_match_2) if (d != end_match_2)
{ {
/* 1 if this match ends in the same string (string1 or string2) /* 1 if this match ends in the same string (string1 or string2)
as the best previous match. */ as the best previous match. */
@ -6058,184 +6148,185 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
else else
best_match_p = !MATCHING_IN_FIRST_STRING; best_match_p = !MATCHING_IN_FIRST_STRING;
DEBUG_PRINT1 ("backtracking.\n"); DEBUG_PRINT1 ("backtracking.\n");
if (!FAIL_STACK_EMPTY ()) if (!FAIL_STACK_EMPTY ())
{ /* More failure points to try. */ { /* More failure points to try. */
/* If exceeds best match so far, save it. */ /* If exceeds best match so far, save it. */
if (!best_regs_set || best_match_p) if (!best_regs_set || best_match_p)
{ {
best_regs_set = true; best_regs_set = true;
match_end = d; match_end = d;
DEBUG_PRINT1 ("\nSAVING match as best so far.\n"); DEBUG_PRINT1 ("\nSAVING match as best so far.\n");
for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
{ {
best_regstart[mcnt] = regstart[mcnt]; best_regstart[mcnt] = regstart[mcnt];
best_regend[mcnt] = regend[mcnt]; best_regend[mcnt] = regend[mcnt];
} }
} }
goto fail; goto fail;
} }
/* If no failure points, don't restore garbage. And if /* If no failure points, don't restore garbage. And if
last match is real best match, don't restore second last match is real best match, don't restore second
best one. */ best one. */
else if (best_regs_set && !best_match_p) else if (best_regs_set && !best_match_p)
{ {
restore_best_regs: restore_best_regs:
/* Restore best match. It may happen that `dend == /* Restore best match. It may happen that `dend ==
end_match_1' while the restored d is in string2. end_match_1' while the restored d is in string2.
For example, the pattern `x.*y.*z' against the For example, the pattern `x.*y.*z' against the
strings `x-' and `y-z-', if the two strings are strings `x-' and `y-z-', if the two strings are
not consecutive in memory. */ not consecutive in memory. */
DEBUG_PRINT1 ("Restoring best registers.\n"); DEBUG_PRINT1 ("Restoring best registers.\n");
d = match_end; d = match_end;
dend = ((d >= string1 && d <= end1) dend = ((d >= string1 && d <= end1)
? end_match_1 : end_match_2); ? end_match_1 : end_match_2);
for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
{ {
regstart[mcnt] = best_regstart[mcnt]; regstart[mcnt] = best_regstart[mcnt];
regend[mcnt] = best_regend[mcnt]; regend[mcnt] = best_regend[mcnt];
} }
} }
} /* d != end_match_2 */ } /* d != end_match_2 */
succeed_label: succeed_label:
DEBUG_PRINT1 ("Accepting match.\n"); DEBUG_PRINT1 ("Accepting match.\n");
/* If caller wants register contents data back, do it. */ /* If caller wants register contents data back, do it. */
if (regs && !bufp->no_sub) if (regs && !bufp->no_sub)
{ {
/* Have the register data arrays been allocated? */ /* Have the register data arrays been allocated? */
if (bufp->regs_allocated == REGS_UNALLOCATED) if (bufp->regs_allocated == REGS_UNALLOCATED)
{ /* No. So allocate them with malloc. We need one { /* No. So allocate them with malloc. We need one
extra element beyond `num_regs' for the `-1' marker extra element beyond `num_regs' for the `-1' marker
GNU code uses. */ GNU code uses. */
regs->num_regs = MAX (RE_NREGS, num_regs + 1); regs->num_regs = MAX (RE_NREGS, num_regs + 1);
regs->start = TALLOC (regs->num_regs, regoff_t); regs->start = TALLOC (regs->num_regs, regoff_t);
regs->end = TALLOC (regs->num_regs, regoff_t); regs->end = TALLOC (regs->num_regs, regoff_t);
if (regs->start == NULL || regs->end == NULL) if (regs->start == NULL || regs->end == NULL)
{ {
FREE_VARIABLES (); FREE_VARIABLES ();
return -2; return -2;
} }
bufp->regs_allocated = REGS_REALLOCATE; bufp->regs_allocated = REGS_REALLOCATE;
} }
else if (bufp->regs_allocated == REGS_REALLOCATE) else if (bufp->regs_allocated == REGS_REALLOCATE)
{ /* Yes. If we need more elements than were already { /* Yes. If we need more elements than were already
allocated, reallocate them. If we need fewer, just allocated, reallocate them. If we need fewer, just
leave it alone. */ leave it alone. */
if (regs->num_regs < num_regs + 1) if (regs->num_regs < num_regs + 1)
{ {
regs->num_regs = num_regs + 1; regs->num_regs = num_regs + 1;
RETALLOC (regs->start, regs->num_regs, regoff_t); RETALLOC (regs->start, regs->num_regs, regoff_t);
RETALLOC (regs->end, regs->num_regs, regoff_t); RETALLOC (regs->end, regs->num_regs, regoff_t);
if (regs->start == NULL || regs->end == NULL) if (regs->start == NULL || regs->end == NULL)
{ {
FREE_VARIABLES (); FREE_VARIABLES ();
return -2; return -2;
} }
} }
} }
else else
{ {
/* These braces fend off a "empty body in an else-statement" /* These braces fend off a "empty body in an else-statement"
warning under GCC when assert expands to nothing. */ warning under GCC when assert expands to nothing. */
assert (bufp->regs_allocated == REGS_FIXED); assert (bufp->regs_allocated == REGS_FIXED);
} }
/* Convert the pointer data in `regstart' and `regend' to /* Convert the pointer data in `regstart' and `regend' to
indices. Register zero has to be set differently, indices. Register zero has to be set differently,
since we haven't kept track of any info for it. */ since we haven't kept track of any info for it. */
if (regs->num_regs > 0) if (regs->num_regs > 0)
{ {
regs->start[0] = pos; regs->start[0] = pos;
#ifdef WCHAR #ifdef WCHAR
if (MATCHING_IN_FIRST_STRING) if (MATCHING_IN_FIRST_STRING)
regs->end[0] = mbs_offset1 != NULL ? regs->end[0] = (mbs_offset1 != NULL ?
mbs_offset1[d-string1] : 0; mbs_offset1[d-string1] : 0);
else else
regs->end[0] = csize1 + (mbs_offset2 != NULL ? regs->end[0] = csize1 + (mbs_offset2 != NULL
mbs_offset2[d-string2] : 0); ? mbs_offset2[d-string2] : 0);
#else #else
regs->end[0] = (MATCHING_IN_FIRST_STRING regs->end[0] = (MATCHING_IN_FIRST_STRING
? ((regoff_t) (d - string1)) ? ((regoff_t) (d - string1))
: ((regoff_t) (d - string2 + size1))); : ((regoff_t) (d - string2 + size1)));
#endif /* WCHAR */ #endif /* WCHAR */
} }
/* Go through the first `min (num_regs, regs->num_regs)' /* Go through the first `min (num_regs, regs->num_regs)'
registers, since that is all we initialized. */ registers, since that is all we initialized. */
for (mcnt = 1; (unsigned) mcnt < MIN (num_regs, regs->num_regs); for (mcnt = 1; (unsigned) mcnt < MIN (num_regs, regs->num_regs);
mcnt++) mcnt++)
{ {
if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt])) if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt]))
regs->start[mcnt] = regs->end[mcnt] = -1; regs->start[mcnt] = regs->end[mcnt] = -1;
else else
{ {
regs->start[mcnt] regs->start[mcnt]
= (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]); = (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]);
regs->end[mcnt] regs->end[mcnt]
= (regoff_t) POINTER_TO_OFFSET (regend[mcnt]); = (regoff_t) POINTER_TO_OFFSET (regend[mcnt]);
} }
} }
/* If the regs structure we return has more elements than /* If the regs structure we return has more elements than
were in the pattern, set the extra elements to -1. If were in the pattern, set the extra elements to -1. If
we (re)allocated the registers, this is the case, we (re)allocated the registers, this is the case,
because we always allocate enough to have at least one because we always allocate enough to have at least one
-1 at the end. */ -1 at the end. */
for (mcnt = num_regs; (unsigned) mcnt < regs->num_regs; mcnt++) for (mcnt = num_regs; (unsigned) mcnt < regs->num_regs; mcnt++)
regs->start[mcnt] = regs->end[mcnt] = -1; regs->start[mcnt] = regs->end[mcnt] = -1;
} /* regs && !bufp->no_sub */ } /* regs && !bufp->no_sub */
DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n", DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n",
nfailure_points_pushed, nfailure_points_popped, nfailure_points_pushed, nfailure_points_popped,
nfailure_points_pushed - nfailure_points_popped); nfailure_points_pushed - nfailure_points_popped);
DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed); DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed);
#ifdef WCHAR #ifdef WCHAR
if (MATCHING_IN_FIRST_STRING) if (MATCHING_IN_FIRST_STRING)
mcnt = mbs_offset1 != NULL ? mbs_offset1[d-string1] : 0; mcnt = mbs_offset1 != NULL ? mbs_offset1[d-string1] : 0;
else else
mcnt = (mbs_offset2 != NULL ? mbs_offset2[d-string2] : 0) + mcnt = (mbs_offset2 != NULL ? mbs_offset2[d-string2] : 0) +
csize1; csize1;
mcnt -= pos; mcnt -= pos;
#else #else
mcnt = d - pos - (MATCHING_IN_FIRST_STRING mcnt = d - pos - (MATCHING_IN_FIRST_STRING
? string1 ? string1 : string2 - size1);
: string2 - size1);
#endif /* WCHAR */ #endif /* WCHAR */
DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt); DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt);
FREE_VARIABLES (); FREE_VARIABLES ();
return mcnt; return mcnt;
} }
#ifndef __GNUC__
/* Otherwise match next pattern command. */ /* Otherwise match next pattern command. */
switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++)) switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++))
{ {
#endif
/* Ignore these. Used to ignore the n of succeed_n's which /* Ignore these. Used to ignore the n of succeed_n's which
currently have n == 0. */ currently have n == 0. */
case no_op: CASE (no_op):
DEBUG_PRINT1 ("EXECUTING no_op.\n"); DEBUG_PRINT1 ("EXECUTING no_op.\n");
break; NEXT;
case succeed: CASE (succeed):
DEBUG_PRINT1 ("EXECUTING succeed.\n"); DEBUG_PRINT1 ("EXECUTING succeed.\n");
goto succeed_label; goto succeed_label;
/* Match the next n pattern characters exactly. The following /* Match the next n pattern characters exactly. The following
byte in the pattern defines n, and the n bytes after that byte in the pattern defines n, and the n bytes after that
are the characters to match. */ are the characters to match. */
case exactn: CASE (exactn):
#ifdef MBS_SUPPORT #ifdef MBS_SUPPORT
case exactn_bin: CASE (exactn_bin):
#endif #endif
mcnt = *p++; mcnt = *p++;
DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt); DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt);
@ -6277,11 +6368,11 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
while (--mcnt); while (--mcnt);
} }
SET_REGS_MATCHED (); SET_REGS_MATCHED ();
break; NEXT;
/* Match any character except possibly a newline or a null. */ /* Match any character except possibly a newline or a null. */
case anychar: CASE (anychar):
DEBUG_PRINT1 ("EXECUTING anychar.\n"); DEBUG_PRINT1 ("EXECUTING anychar.\n");
PREFETCH (); PREFETCH ();
@ -6293,11 +6384,11 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
SET_REGS_MATCHED (); SET_REGS_MATCHED ();
DEBUG_PRINT2 (" Matched `%ld'.\n", (long int) *d); DEBUG_PRINT2 (" Matched `%ld'.\n", (long int) *d);
d++; d++;
break; NEXT;
case charset: CASE (charset):
case charset_not: CASE (charset_not):
{ {
register UCHAR_T c; register UCHAR_T c;
#ifdef WCHAR #ifdef WCHAR
@ -6697,7 +6788,7 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
#endif /* WCHAR */ #endif /* WCHAR */
SET_REGS_MATCHED (); SET_REGS_MATCHED ();
d++; d++;
break; NEXT;
} }
@ -6706,7 +6797,7 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
number of groups inner to this one in the next. The text number of groups inner to this one in the next. The text
matched within the group is recorded (in the internal matched within the group is recorded (in the internal
registers data structure) under the register number. */ registers data structure) under the register number. */
case start_memory: CASE (start_memory):
DEBUG_PRINT3 ("EXECUTING start_memory %ld (%ld):\n", DEBUG_PRINT3 ("EXECUTING start_memory %ld (%ld):\n",
(long int) *p, (long int) p[1]); (long int) *p, (long int) p[1]);
@ -6749,13 +6840,13 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
p += 2; p += 2;
just_past_start_mem = p; just_past_start_mem = p;
break; NEXT;
/* The stop_memory opcode represents the end of a group. Its /* The stop_memory opcode represents the end of a group. Its
arguments are the same as start_memory's: the register arguments are the same as start_memory's: the register
number, and the number of inner groups. */ number, and the number of inner groups. */
case stop_memory: CASE (stop_memory):
DEBUG_PRINT3 ("EXECUTING stop_memory %ld (%ld):\n", DEBUG_PRINT3 ("EXECUTING stop_memory %ld (%ld):\n",
(long int) *p, (long int) p[1]); (long int) *p, (long int) p[1]);
@ -6888,12 +6979,12 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
/* Move past the register number and the inner group count. */ /* Move past the register number and the inner group count. */
p += 2; p += 2;
break; NEXT;
/* \<digit> has been turned into a `duplicate' command which is /* \<digit> has been turned into a `duplicate' command which is
followed by the numeric value of <digit> as the register number. */ followed by the numeric value of <digit> as the register number. */
case duplicate: CASE (duplicate):
{ {
register const CHAR_T *d2, *dend2; register const CHAR_T *d2, *dend2;
int regno = *p++; /* Get which register to match against. */ int regno = *p++; /* Get which register to match against. */
@ -6953,58 +7044,68 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
SET_REGS_MATCHED (); SET_REGS_MATCHED ();
} }
} }
break; NEXT;
/* begline matches the empty string at the beginning of the string /* begline matches the empty string at the beginning of the string
(unless `not_bol' is set in `bufp'), and, if (unless `not_bol' is set in `bufp'), and, if
`newline_anchor' is set, after newlines. */ `newline_anchor' is set, after newlines. */
case begline: CASE (begline):
DEBUG_PRINT1 ("EXECUTING begline.\n"); DEBUG_PRINT1 ("EXECUTING begline.\n");
if (AT_STRINGS_BEG (d)) if (AT_STRINGS_BEG (d))
{ {
if (!bufp->not_bol) break; if (!bufp->not_bol)
{
NEXT;
}
} }
else if (d[-1] == '\n' && bufp->newline_anchor) else if (d[-1] == '\n' && bufp->newline_anchor)
{ {
break; NEXT;
} }
/* In all other cases, we fail. */ /* In all other cases, we fail. */
goto fail; goto fail;
/* endline is the dual of begline. */ /* endline is the dual of begline. */
case endline: CASE (endline):
DEBUG_PRINT1 ("EXECUTING endline.\n"); DEBUG_PRINT1 ("EXECUTING endline.\n");
if (AT_STRINGS_END (d)) if (AT_STRINGS_END (d))
{ {
if (!bufp->not_eol) break; if (!bufp->not_eol)
{
NEXT;
}
} }
/* We have to ``prefetch'' the next character. */ /* We have to ``prefetch'' the next character. */
else if ((d == end1 ? *string2 : *d) == '\n' else if ((d == end1 ? *string2 : *d) == '\n'
&& bufp->newline_anchor) && bufp->newline_anchor)
{ {
break; NEXT;
} }
goto fail; goto fail;
/* Match at the very beginning of the data. */ /* Match at the very beginning of the data. */
case begbuf: CASE (begbuf):
DEBUG_PRINT1 ("EXECUTING begbuf.\n"); DEBUG_PRINT1 ("EXECUTING begbuf.\n");
if (AT_STRINGS_BEG (d)) if (AT_STRINGS_BEG (d))
break; {
NEXT;
}
goto fail; goto fail;
/* Match at the very end of the data. */ /* Match at the very end of the data. */
case endbuf: CASE (endbuf):
DEBUG_PRINT1 ("EXECUTING endbuf.\n"); DEBUG_PRINT1 ("EXECUTING endbuf.\n");
if (AT_STRINGS_END (d)) if (AT_STRINGS_END (d))
break; {
NEXT;
}
goto fail; goto fail;
@ -7024,7 +7125,7 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
stack at all is that otherwise we would have to change stack at all is that otherwise we would have to change
`anychar's code to do something besides goto fail in this `anychar's code to do something besides goto fail in this
case; that seems worse than this. */ case; that seems worse than this. */
case on_failure_keep_string_jump: CASE (on_failure_keep_string_jump):
DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump"); DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump");
EXTRACT_NUMBER_AND_INCR (mcnt, p); EXTRACT_NUMBER_AND_INCR (mcnt, p);
@ -7035,7 +7136,7 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
#endif #endif
PUSH_FAILURE_POINT (p + mcnt, NULL, -2); PUSH_FAILURE_POINT (p + mcnt, NULL, -2);
break; NEXT;
/* Uses of on_failure_jump: /* Uses of on_failure_jump:
@ -7050,7 +7151,7 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
Repeats start with an on_failure_jump that points past both Repeats start with an on_failure_jump that points past both
the repetition text and either the following jump or the repetition text and either the following jump or
pop_failure_jump back to this on_failure_jump. */ pop_failure_jump back to this on_failure_jump. */
case on_failure_jump: CASE (on_failure_jump):
on_failure: on_failure:
DEBUG_PRINT1 ("EXECUTING on_failure_jump"); DEBUG_PRINT1 ("EXECUTING on_failure_jump");
@ -7092,12 +7193,12 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
DEBUG_PRINT1 (":\n"); DEBUG_PRINT1 (":\n");
PUSH_FAILURE_POINT (p + mcnt, d, -2); PUSH_FAILURE_POINT (p + mcnt, d, -2);
break; NEXT;
/* A smart repeat ends with `maybe_pop_jump'. /* A smart repeat ends with `maybe_pop_jump'.
We change it to either `pop_failure_jump' or `jump'. */ We change it to either `pop_failure_jump' or `jump'. */
case maybe_pop_jump: CASE (maybe_pop_jump):
EXTRACT_NUMBER_AND_INCR (mcnt, p); EXTRACT_NUMBER_AND_INCR (mcnt, p);
DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt); DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt);
{ {
@ -7265,7 +7366,7 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
points put on by this pop_failure_jump's matching points put on by this pop_failure_jump's matching
on_failure_jump; we got through the pattern to here from the on_failure_jump; we got through the pattern to here from the
matching on_failure_jump, so didn't fail. */ matching on_failure_jump, so didn't fail. */
case pop_failure_jump: CASE (pop_failure_jump):
{ {
/* We need to pass separate storage for the lowest and /* We need to pass separate storage for the lowest and
highest registers, even though we don't care about the highest registers, even though we don't care about the
@ -7292,7 +7393,7 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
/* Note fall through. */ /* Note fall through. */
/* Unconditionally jump (without popping any failure points). */ /* Unconditionally jump (without popping any failure points). */
case jump: CASE (jump):
EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */ EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */
DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt); DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt);
p += mcnt; /* Do the jump. */ p += mcnt; /* Do the jump. */
@ -7301,12 +7402,12 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
#else #else
DEBUG_PRINT2 ("(to 0x%x).\n", p); DEBUG_PRINT2 ("(to 0x%x).\n", p);
#endif #endif
break; NEXT;
/* We need this opcode so we can detect where alternatives end /* We need this opcode so we can detect where alternatives end
in `group_match_null_string_p' et al. */ in `group_match_null_string_p' et al. */
case jump_past_alt: CASE (jump_past_alt):
DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n"); DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n");
goto unconditional_jump; goto unconditional_jump;
@ -7316,7 +7417,7 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
pop_failure_jump, also, and with a pattern of, say, `a+', we pop_failure_jump, also, and with a pattern of, say, `a+', we
are skipping over the on_failure_jump, so we have to push are skipping over the on_failure_jump, so we have to push
something meaningless for pop_failure_jump to pop. */ something meaningless for pop_failure_jump to pop. */
case dummy_failure_jump: CASE (dummy_failure_jump):
DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n"); DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n");
/* It doesn't matter what we push for the string here. What /* It doesn't matter what we push for the string here. What
the code at `fail' tests is the value for the pattern. */ the code at `fail' tests is the value for the pattern. */
@ -7329,16 +7430,16 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
we don't want the failure point for the alternative to be we don't want the failure point for the alternative to be
popped. For example, matching `(a|ab)*' against `aab' popped. For example, matching `(a|ab)*' against `aab'
requires that we match the `ab' alternative. */ requires that we match the `ab' alternative. */
case push_dummy_failure: CASE (push_dummy_failure):
DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n"); DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n");
/* See comments just above at `dummy_failure_jump' about the /* See comments just above at `dummy_failure_jump' about the
two zeroes. */ two zeroes. */
PUSH_FAILURE_POINT (NULL, NULL, -2); PUSH_FAILURE_POINT (NULL, NULL, -2);
break; NEXT;
/* Have to succeed matching what follows at least n times. /* Have to succeed matching what follows at least n times.
After that, handle like `on_failure_jump'. */ After that, handle like `on_failure_jump'. */
case succeed_n: CASE (succeed_n):
EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE); EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE);
DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt); DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt);
@ -7375,9 +7476,9 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
#endif /* WCHAR */ #endif /* WCHAR */
goto on_failure; goto on_failure;
} }
break; NEXT;
case jump_n: CASE (jump_n):
EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE); EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE);
DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt); DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt);
@ -7399,9 +7500,9 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
/* If don't have to jump any more, skip over the rest of command. */ /* If don't have to jump any more, skip over the rest of command. */
else else
p += 2 * OFFSET_ADDRESS_SIZE; p += 2 * OFFSET_ADDRESS_SIZE;
break; NEXT;
case set_number_at: CASE (set_number_at):
{ {
DEBUG_PRINT1 ("EXECUTING set_number_at.\n"); DEBUG_PRINT1 ("EXECUTING set_number_at.\n");
@ -7414,7 +7515,7 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt); DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt);
#endif #endif
STORE_NUMBER (p1, mcnt); STORE_NUMBER (p1, mcnt);
break; NEXT;
} }
#if 0 #if 0
@ -7423,34 +7524,40 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
AT_WORD_BOUNDARY, so this code is disabled. Expanding the AT_WORD_BOUNDARY, so this code is disabled. Expanding the
macro and introducing temporary variables works around the bug. */ macro and introducing temporary variables works around the bug. */
case wordbound: CASE (wordbound):
DEBUG_PRINT1 ("EXECUTING wordbound.\n"); DEBUG_PRINT1 ("EXECUTING wordbound.\n");
if (AT_WORD_BOUNDARY (d)) if (AT_WORD_BOUNDARY (d))
break; {
NEXT;
}
goto fail; goto fail;
case notwordbound: CASE (notwordbound):
DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
if (AT_WORD_BOUNDARY (d)) if (AT_WORD_BOUNDARY (d))
goto fail; goto fail;
break; NEXT;
#else #else
case wordbound: CASE (wordbound):
{ {
boolean prevchar, thischar; boolean prevchar, thischar;
DEBUG_PRINT1 ("EXECUTING wordbound.\n"); DEBUG_PRINT1 ("EXECUTING wordbound.\n");
if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)) if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d))
break; {
NEXT;
}
prevchar = WORDCHAR_P (d - 1); prevchar = WORDCHAR_P (d - 1);
thischar = WORDCHAR_P (d); thischar = WORDCHAR_P (d);
if (prevchar != thischar) if (prevchar != thischar)
break; {
NEXT;
}
goto fail; goto fail;
} }
case notwordbound: CASE (notwordbound):
{ {
boolean prevchar, thischar; boolean prevchar, thischar;
@ -7462,49 +7569,53 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
thischar = WORDCHAR_P (d); thischar = WORDCHAR_P (d);
if (prevchar != thischar) if (prevchar != thischar)
goto fail; goto fail;
break; NEXT;
} }
#endif #endif
case wordbeg: CASE (wordbeg):
DEBUG_PRINT1 ("EXECUTING wordbeg.\n"); DEBUG_PRINT1 ("EXECUTING wordbeg.\n");
if (!AT_STRINGS_END (d) && WORDCHAR_P (d) if (!AT_STRINGS_END (d) && WORDCHAR_P (d)
&& (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1))) && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1)))
break; {
NEXT;
}
goto fail; goto fail;
case wordend: CASE (wordend):
DEBUG_PRINT1 ("EXECUTING wordend.\n"); DEBUG_PRINT1 ("EXECUTING wordend.\n");
if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1) if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1)
&& (AT_STRINGS_END (d) || !WORDCHAR_P (d))) && (AT_STRINGS_END (d) || !WORDCHAR_P (d)))
break; {
NEXT;
}
goto fail; goto fail;
#ifdef emacs #ifdef emacs
case before_dot: CASE (before_dot):
DEBUG_PRINT1 ("EXECUTING before_dot.\n"); DEBUG_PRINT1 ("EXECUTING before_dot.\n");
if (PTR_CHAR_POS ((unsigned char *) d) >= point) if (PTR_CHAR_POS ((unsigned char *) d) >= point)
goto fail; goto fail;
break; NEXT;
case at_dot: CASE (at_dot):
DEBUG_PRINT1 ("EXECUTING at_dot.\n"); DEBUG_PRINT1 ("EXECUTING at_dot.\n");
if (PTR_CHAR_POS ((unsigned char *) d) != point) if (PTR_CHAR_POS ((unsigned char *) d) != point)
goto fail; goto fail;
break; NEXT;
case after_dot: CASE (after_dot):
DEBUG_PRINT1 ("EXECUTING after_dot.\n"); DEBUG_PRINT1 ("EXECUTING after_dot.\n");
if (PTR_CHAR_POS ((unsigned char *) d) <= point) if (PTR_CHAR_POS ((unsigned char *) d) <= point)
goto fail; goto fail;
break; NEXT;
case syntaxspec: CASE (syntaxspec):
DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt); DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt);
mcnt = *p++; mcnt = *p++;
goto matchsyntax; goto matchsyntax;
case wordchar: CASE (wordchar):
DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n"); DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n");
mcnt = (int) Sword; mcnt = (int) Sword;
matchsyntax: matchsyntax:
@ -7514,14 +7625,14 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
if (SYNTAX (d[-1]) != (enum syntaxcode) mcnt) if (SYNTAX (d[-1]) != (enum syntaxcode) mcnt)
goto fail; goto fail;
SET_REGS_MATCHED (); SET_REGS_MATCHED ();
break; NEXT;
case notsyntaxspec: CASE (notsyntaxspec):
DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt); DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt);
mcnt = *p++; mcnt = *p++;
goto matchnotsyntax; goto matchnotsyntax;
case notwordchar: CASE (notwordchar):
DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n"); DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n");
mcnt = (int) Sword; mcnt = (int) Sword;
matchnotsyntax: matchnotsyntax:
@ -7531,32 +7642,34 @@ byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
if (SYNTAX (d[-1]) == (enum syntaxcode) mcnt) if (SYNTAX (d[-1]) == (enum syntaxcode) mcnt)
goto fail; goto fail;
SET_REGS_MATCHED (); SET_REGS_MATCHED ();
break; NEXT;
#else /* not emacs */ #else /* not emacs */
case wordchar: CASE (wordchar):
DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n"); DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n");
PREFETCH (); PREFETCH ();
if (!WORDCHAR_P (d)) if (!WORDCHAR_P (d))
goto fail; goto fail;
SET_REGS_MATCHED (); SET_REGS_MATCHED ();
d++; d++;
break; NEXT;
case notwordchar: CASE (notwordchar):
DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n"); DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n");
PREFETCH (); PREFETCH ();
if (WORDCHAR_P (d)) if (WORDCHAR_P (d))
goto fail; goto fail;
SET_REGS_MATCHED (); SET_REGS_MATCHED ();
d++; d++;
break; NEXT;
#endif /* not emacs */ #endif /* not emacs */
#ifndef __GNUC__
default: default:
abort (); abort ();
} }
continue; /* Successfully executed one pattern command; keep going. */ continue; /* Successfully executed one pattern command; keep going. */
#endif
/* We goto here if a matching operation fails. */ /* We goto here if a matching operation fails. */