/[emacs]/emacs/src/regex.c
ViewVC logotype

Diff of /emacs/src/regex.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.180 by rms, Mon Sep 9 19:41:30 2002 UTC revision 1.181 by monnier, Tue Sep 10 05:59:32 2002 UTC
# Line 19  Line 19 
19     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20     USA.  */     USA.  */
21    
22  /* BUGS:  /* TODO:
    - (x?)*y\1z should match both xxxxyxz and xxxyz.  
    TODO:  
23     - structure the opcode space into opcode+flag.     - structure the opcode space into opcode+flag.
24     - merge with glibc's regex.[ch].     - merge with glibc's regex.[ch].
25     - replace (succeed_n + jump_n + set_number_at) with something that doesn't     - replace (succeed_n + jump_n + set_number_at) with something that doesn't
# Line 1520  do {                                                                   \ Line 1518  do {                                                                   \
1518      }                                                                   \      }                                                                   \
1519  } while (0)  } while (0)
1520    
 /* Discard a saved register off the stack.  */  
 #define DISCARD_FAILURE_REG_OR_COUNT()                                  \  
 do {                                                                    \  
   int reg = POP_FAILURE_INT ();                                         \  
   if (reg == -1)                                                        \  
     {                                                                   \  
       /* It's a counter.  */                                            \  
       POP_FAILURE_POINTER ();                                           \  
       reg = POP_FAILURE_INT ();                                         \  
       DEBUG_PRINT3 ("     Discard counter %p = %d\n", ptr, reg);        \  
     }                                                                   \  
   else                                                                  \  
     {                                                                   \  
       POP_FAILURE_POINTER ();                                           \  
       POP_FAILURE_POINTER ();                                           \  
       DEBUG_PRINT4 ("     Discard reg %d (spanning %p -> %p)\n",        \  
                     reg, regstart[reg], regend[reg]);                   \  
     }                                                                   \  
 } while (0)  
   
1521  /* Check that we are not stuck in an infinite loop.  */  /* Check that we are not stuck in an infinite loop.  */
1522  #define CHECK_INFINITE_LOOP(pat_cur, string_place)                      \  #define CHECK_INFINITE_LOOP(pat_cur, string_place)                      \
1523  do {                                                                    \  do {                                                                    \
# Line 1553  do {                                                                   \ Line 1531  do {                                                                   \
1531                && FAILURE_PAT (failure) <= bufp->buffer + bufp->used);   \                && FAILURE_PAT (failure) <= bufp->buffer + bufp->used);   \
1532        if (FAILURE_PAT (failure) == pat_cur)                             \        if (FAILURE_PAT (failure) == pat_cur)                             \
1533          {                                                               \          {                                                               \
1534            while (fail_stack.frame < fail_stack.avail)                   \            cycle = 1;                                                    \
1535              DISCARD_FAILURE_REG_OR_COUNT ();                            \            break;                                                        \
           goto fail;                                                    \  
1536          }                                                               \          }                                                               \
1537        DEBUG_PRINT2 ("  Other pattern: %p\n", FAILURE_PAT (failure));    \        DEBUG_PRINT2 ("  Other pattern: %p\n", FAILURE_PAT (failure));    \
1538        failure = NEXT_FAILURE_HANDLE(failure);                           \        failure = NEXT_FAILURE_HANDLE(failure);                           \
1539      }                                                                   \      }                                                                   \
1540    DEBUG_PRINT2 ("  Other string: %p\n", FAILURE_STR (failure));         \    DEBUG_PRINT2 ("  Other string: %p\n", FAILURE_STR (failure));         \
1541  } while (0)  } while (0)
1542        
1543  /* Push the information about the state we will need  /* Push the information about the state we will need
1544     if we ever fail back to it.     if we ever fail back to it.
1545    
# Line 2645  regex_compile (pattern, size, syntax, bu Line 2622  regex_compile (pattern, size, syntax, bu
2622                      unsigned int startoffset = 0;                      unsigned int startoffset = 0;
2623                      re_opcode_t ofj =                      re_opcode_t ofj =
2624                        /* Check if the loop can match the empty string.  */                        /* Check if the loop can match the empty string.  */
2625                        (simple || !analyse_first (laststart, b, NULL, 0)) ?                        (simple || !analyse_first (laststart, b, NULL, 0))
2626                        on_failure_jump : on_failure_jump_loop;                        ? on_failure_jump : on_failure_jump_loop;
2627                      assert (skip_one_char (laststart) <= b);                      assert (skip_one_char (laststart) <= b);
2628                                            
2629                      if (!zero_times_ok && simple)                      if (!zero_times_ok && simple)
# Line 2694  regex_compile (pattern, size, syntax, bu Line 2671  regex_compile (pattern, size, syntax, bu
2671                    {                    {
2672                      boolean emptyp = analyse_first (laststart, b, NULL, 0);                      boolean emptyp = analyse_first (laststart, b, NULL, 0);
2673    
2674                      /* The non-greedy multiple match looks like a repeat..until:                      /* The non-greedy multiple match looks like
2675                         we only need a conditional jump at the end of the loop */                         a repeat..until: we only need a conditional jump
2676                           at the end of the loop.  */
2677                      if (emptyp) BUF_PUSH (no_op);                      if (emptyp) BUF_PUSH (no_op);
2678                      STORE_JUMP (emptyp ? on_failure_jump_nastyloop                      STORE_JUMP (emptyp ? on_failure_jump_nastyloop
2679                                  : on_failure_jump, b, laststart);                                  : on_failure_jump, b, laststart);
# Line 2704  regex_compile (pattern, size, syntax, bu Line 2682  regex_compile (pattern, size, syntax, bu
2682                        {                        {
2683                          /* The repeat...until naturally matches one or more.                          /* The repeat...until naturally matches one or more.
2684                             To also match zero times, we need to first jump to                             To also match zero times, we need to first jump to
2685                             the end of the loop (its conditional jump). */                             the end of the loop (its conditional jump).  */
2686                          INSERT_JUMP (jump, laststart, b);                          INSERT_JUMP (jump, laststart, b);
2687                          b += 3;                          b += 3;
2688                        }                        }
# Line 3241  regex_compile (pattern, size, syntax, bu Line 3219  regex_compile (pattern, size, syntax, bu
3219                        goto unfetch_interval;                        goto unfetch_interval;
3220                    }                    }
3221    
3222                   if (upper_bound == 0)                  if (upper_bound == 0)
3223                     /* If the upper bound is zero, just drop the sub pattern                    /* If the upper bound is zero, just drop the sub pattern
3224                        altogether.  */                       altogether.  */
3225                     b = laststart;                    b = laststart;
3226                   else if (lower_bound == 1 && upper_bound == 1)                  else if (lower_bound == 1 && upper_bound == 1)
3227                     /* Just match it once: nothing to do here.  */                    /* Just match it once: nothing to do here.  */
3228                     ;                    ;
3229    
3230                   /* Otherwise, we have a nontrivial interval.  When                  /* Otherwise, we have a nontrivial interval.  When
3231                      we're all done, the pattern will look like:                     we're all done, the pattern will look like:
3232                        set_number_at <jump count> <upper bound>                     set_number_at <jump count> <upper bound>
3233                        set_number_at <succeed_n count> <lower bound>                     set_number_at <succeed_n count> <lower bound>
3234                        succeed_n <after jump addr> <succeed_n count>                     succeed_n <after jump addr> <succeed_n count>
3235                        <body of loop>                     <body of loop>
3236                        jump_n <succeed_n addr> <jump count>                     jump_n <succeed_n addr> <jump count>
3237                      (The upper bound and `jump_n' are omitted if                     (The upper bound and `jump_n' are omitted if
3238                      `upper_bound' is 1, though.)  */                     `upper_bound' is 1, though.)  */
3239                   else                  else
3240                     { /* If the upper bound is > 1, we need to insert                    { /* If the upper bound is > 1, we need to insert
3241                          more at the end of the loop.  */                         more at the end of the loop.  */
3242                       unsigned int nbytes = (upper_bound < 0 ? 3                      unsigned int nbytes = (upper_bound < 0 ? 3
3243                                              : upper_bound > 1 ? 5 : 0);                                             : upper_bound > 1 ? 5 : 0);
3244                       unsigned int startoffset = 0;                      unsigned int startoffset = 0;
3245    
3246                       GET_BUFFER_SPACE (20); /* We might use less.  */                      GET_BUFFER_SPACE (20); /* We might use less.  */
3247    
3248                       if (lower_bound == 0)                      if (lower_bound == 0)
3249                         {                        {
3250                           /* A succeed_n that starts with 0 is really a                          /* A succeed_n that starts with 0 is really a
3251                              a simple on_failure_jump_loop.  */                             a simple on_failure_jump_loop.  */
3252                           INSERT_JUMP (on_failure_jump_loop, laststart,                          INSERT_JUMP (on_failure_jump_loop, laststart,
3253                                        b + 3 + nbytes);                                       b + 3 + nbytes);
3254                           b += 3;                          b += 3;
3255                         }                        }
3256                       else                      else
3257                         {                        {
3258                           /* Initialize lower bound of the `succeed_n', even                          /* Initialize lower bound of the `succeed_n', even
3259                              though it will be set during matching by its                             though it will be set during matching by its
3260                              attendant `set_number_at' (inserted next),                             attendant `set_number_at' (inserted next),
3261                              because `re_compile_fastmap' needs to know.                             because `re_compile_fastmap' needs to know.
3262                              Jump to the `jump_n' we might insert below.  */                             Jump to the `jump_n' we might insert below.  */
3263                           INSERT_JUMP2 (succeed_n, laststart,                          INSERT_JUMP2 (succeed_n, laststart,
3264                                         b + 5 + nbytes,                                        b + 5 + nbytes,
3265                                         lower_bound);                                        lower_bound);
3266                           b += 5;                          b += 5;
3267    
3268                           /* Code to initialize the lower bound.  Insert                          /* Code to initialize the lower bound.  Insert
3269                              before the `succeed_n'.      The `5' is the last two                             before the `succeed_n'.       The `5' is the last two
3270                              bytes of this `set_number_at', plus 3 bytes of                             bytes of this `set_number_at', plus 3 bytes of
3271                              the following `succeed_n'.  */                             the following `succeed_n'.  */
3272                           insert_op2 (set_number_at, laststart, 5, lower_bound, b);                          insert_op2 (set_number_at, laststart, 5, lower_bound, b);
3273                           b += 5;                          b += 5;
3274                           startoffset += 5;                          startoffset += 5;
3275                         }                        }
3276    
3277                       if (upper_bound < 0)                      if (upper_bound < 0)
3278                         {                        {
3279                           /* A negative upper bound stands for infinity,                          /* A negative upper bound stands for infinity,
3280                              in which case it degenerates to a plain jump.  */                             in which case it degenerates to a plain jump.  */
3281                           STORE_JUMP (jump, b, laststart + startoffset);                          STORE_JUMP (jump, b, laststart + startoffset);
3282                           b += 3;                          b += 3;
3283                         }                        }
3284                       else if (upper_bound > 1)                      else if (upper_bound > 1)
3285                         { /* More than one repetition is allowed, so                        { /* More than one repetition is allowed, so
3286                              append a backward jump to the `succeed_n'                             append a backward jump to the `succeed_n'
3287                              that starts this interval.                             that starts this interval.
3288    
3289                              When we've reached this during matching,                             When we've reached this during matching,
3290                              we'll have matched the interval once, so                             we'll have matched the interval once, so
3291                              jump back only `upper_bound - 1' times.  */                             jump back only `upper_bound - 1' times.  */
3292                           STORE_JUMP2 (jump_n, b, laststart + startoffset,                          STORE_JUMP2 (jump_n, b, laststart + startoffset,
3293                                        upper_bound - 1);                                       upper_bound - 1);
3294                           b += 5;                          b += 5;
3295    
3296                           /* The location we want to set is the second                          /* The location we want to set is the second
3297                              parameter of the `jump_n'; that is `b-2' as                             parameter of the `jump_n'; that is `b-2' as
3298                              an absolute address.  `laststart' will be                             an absolute address.  `laststart' will be
3299                              the `set_number_at' we're about to insert;                             the `set_number_at' we're about to insert;
3300                              `laststart+3' the number to set, the source                             `laststart+3' the number to set, the source
3301                              for the relative address.  But we are                             for the relative address.  But we are
3302                              inserting into the middle of the pattern --                             inserting into the middle of the pattern --
3303                              so everything is getting moved up by 5.                             so everything is getting moved up by 5.
3304                              Conclusion: (b - 2) - (laststart + 3) + 5,                             Conclusion: (b - 2) - (laststart + 3) + 5,
3305                              i.e., b - laststart.                             i.e., b - laststart.
3306    
3307                              We insert this at the beginning of the loop                             We insert this at the beginning of the loop
3308                              so that if we fail during matching, we'll                             so that if we fail during matching, we'll
3309                              reinitialize the bounds.  */                             reinitialize the bounds.  */
3310                           insert_op2 (set_number_at, laststart, b - laststart,                          insert_op2 (set_number_at, laststart, b - laststart,
3311                                       upper_bound - 1, b);                                      upper_bound - 1, b);
3312                           b += 5;                          b += 5;
3313                         }                        }
3314                     }                    }
3315                  pending_exact = 0;                  pending_exact = 0;
3316                  beg_interval = NULL;                  beg_interval = NULL;
3317                }                }
# Line 5518  re_match_2_internal (bufp, string1, size Line 5496  re_match_2_internal (bufp, string1, size
5496               cycle detection cannot work.  Worse yet, such a detection               cycle detection cannot work.  Worse yet, such a detection
5497               can not only fail to detect a cycle, but it can also wrongly               can not only fail to detect a cycle, but it can also wrongly
5498               detect a cycle (between different instantiations of the same               detect a cycle (between different instantiations of the same
5499               loop.               loop).
5500               So the method used for those nasty loops is a little different:               So the method used for those nasty loops is a little different:
5501               We use a special cycle-detection-stack-frame which is pushed               We use a special cycle-detection-stack-frame which is pushed
5502               when the on_failure_jump_nastyloop failure-point is *popped*.               when the on_failure_jump_nastyloop failure-point is *popped*.
# Line 5532  re_match_2_internal (bufp, string1, size Line 5510  re_match_2_internal (bufp, string1, size
5510                          mcnt, p + mcnt);                          mcnt, p + mcnt);
5511    
5512            assert ((re_opcode_t)p[-4] == no_op);            assert ((re_opcode_t)p[-4] == no_op);
5513            CHECK_INFINITE_LOOP (p - 4, d);            {
5514            PUSH_FAILURE_POINT (p - 3, d);              int cycle = 0;
5515                CHECK_INFINITE_LOOP (p - 4, d);
5516                if (!cycle)
5517                  /* If there's a cycle, just continue without pushing
5518                     this failure point.  The failure point is the "try again"
5519                     option, which shouldn't be tried.
5520                     We want (x?)*?y\1z to match both xxyz and xxyxz.  */
5521                  PUSH_FAILURE_POINT (p - 3, d);
5522              }
5523            break;            break;
5524    
   
5525            /* Simple loop detecting on_failure_jump:  just check on the            /* Simple loop detecting on_failure_jump:  just check on the
5526               failure stack if the same spot was already hit earlier.  */               failure stack if the same spot was already hit earlier.  */
5527          case on_failure_jump_loop:          case on_failure_jump_loop:
# Line 5544  re_match_2_internal (bufp, string1, size Line 5529  re_match_2_internal (bufp, string1, size
5529            EXTRACT_NUMBER_AND_INCR (mcnt, p);            EXTRACT_NUMBER_AND_INCR (mcnt, p);
5530            DEBUG_PRINT3 ("EXECUTING on_failure_jump_loop %d (to %p):\n",            DEBUG_PRINT3 ("EXECUTING on_failure_jump_loop %d (to %p):\n",
5531                          mcnt, p + mcnt);                          mcnt, p + mcnt);
5532              {
5533            CHECK_INFINITE_LOOP (p - 3, d);              int cycle = 0;
5534            PUSH_FAILURE_POINT (p - 3, d);              CHECK_INFINITE_LOOP (p - 3, d);
5535                if (cycle)
5536                  /* If there's a cycle, get out of the loop, as if the matching
5537                     had failed.  We used to just `goto fail' here, but that was
5538                     aborting the search a bit too early: we want to keep the
5539                     empty-loop-match and keep matching after the loop.
5540                     We want (x?)*y\1z to match both xxyz and xxyxz.  */
5541                  p += mcnt;
5542                else
5543                  PUSH_FAILURE_POINT (p - 3, d);
5544              }
5545            break;            break;
5546    
5547    

Legend:
Removed from v.1.180  
changed lines
  Added in v.1.181

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26