source: scripts/patches/grep-2.5.1a-redhat_fixes-2.patch@ 5ff8cf2

clfs-1.2 clfs-2.1 clfs-3.0.0-systemd clfs-3.0.0-sysvinit systemd sysvinit
Last change on this file since 5ff8cf2 was c0cf39e, checked in by Jim Gifford <clfs@…>, 19 years ago

r2506@server (orig r1245): ryan | 2006-03-10 02:07:10 -0800

r1295@rei: lfs | 2006-03-09 18:29:16 +1100
Add grep-2.5.1a-redhat_fixes-2.patch
------------------------------------
Submitted by: Alexander E. Patrakov
Date: 2005-08-13
Initial Package Version: 2.5.1a
Upstream Status: Partially accepted, partially rejected, but required for LSB >= 2.0 certification
Origin: RedHat
Description: Various fixes from RedHat. Individual patches:


grep-2.5.1-fgrep.patch
grep-2.5.1-bracket.patch
grep-2.5-i18n.patch
grep-2.5.1-oi.patch
grep-2.5.1-manpage.patch
grep-2.5.1-color.patch
grep-2.5.1-icolor.patch
grep-2.5.1-egf-speedup.patch
grep-2.5.1-dfa-optional.patch
grep-2.5.1-tests.patch
grep-2.5.1-w.patch


Testcases:


-fgrep: ???, but required for other patches
-bracket: echo "[" | LANG=en_US.UTF-8 grep ":space:"
-i18n: many fixes for multibyte locale support, required for LSB.
-oi: echo xxYYzz | LANG=C grep -i -o yy
-manpage: typo
-color: restore the background color correctly
-icolor: ??? echo 'spam foo SPAM FOO' | grep -i --color spam

(but that's also fixed by -oi. Is this patch just a cleanup?)

-egf-speedup: without this, grep is as slow as a snail in UTF-8 locales.
-dfa-optional: disables dfa in multibyte locales by default.
-w: (echo 'foo';echo 'fo') > /tmp/testfile && grep -F -w fo /tmp/testfile



  • Property mode set to 100644
File size: 54.8 KB
  • doc/grep.1

    Submitted by: Alexander E. Patrakov
    Date: 2005-08-13
    Initial Package Version: 2.5.1a
    Upstream Status: Partially accepted, partially rejected, but required for LSB >= 2.0 certification
    Origin: RedHat
    Description: Various fixes from RedHat. Individual patches:
    
       grep-2.5.1-fgrep.patch
       grep-2.5.1-bracket.patch
       grep-2.5-i18n.patch
       grep-2.5.1-oi.patch
       grep-2.5.1-manpage.patch
       grep-2.5.1-color.patch
       grep-2.5.1-icolor.patch
       grep-2.5.1-egf-speedup.patch
       grep-2.5.1-dfa-optional.patch
       grep-2.5.1-tests.patch
       grep-2.5.1-w.patch
    
    Testcases:
    
     -fgrep: ???, but required for other patches
     -bracket: echo "[" | LANG=en_US.UTF-8 grep "[[:space:]]"
     -i18n: many fixes for multibyte locale support, required for LSB.
     -oi: echo xxYYzz | LANG=C grep -i -o yy
     -manpage: typo
     -color: restore the background color correctly
     -icolor: ??? echo 'spam foo SPAM FOO' | grep -i --color spam
         (but that's also fixed by -oi. Is this patch just a cleanup?)
     -egf-speedup: without this, grep is as slow as a snail in UTF-8 locales.
     -dfa-optional: disables dfa in multibyte locales by default.
     -w: (echo 'foo';echo 'fo') > /tmp/testfile && grep -F -w fo /tmp/testfile
    
    diff -urN grep-2.5.1a.orig/doc/grep.1 grep-2.5.1a/doc/grep.1
    old new  
    191191.I PATTERN
    192192as a list of fixed strings, separated by newlines,
    193193any of which is to be matched.
     194.TP
    194195.BR \-P ", " \-\^\-perl-regexp
    195196Interpret
    196197.I PATTERN
     
    302303This is especially useful for tools like zgrep, e.g.
    303304.B "gzip -cd foo.gz |grep --label=foo something"
    304305.TP
    305 .BR \-\^\-line-buffering
     306.BR \-\^\-line-buffered
    306307Use line buffering, it can be a performance penality.
    307308.TP
    308309.BR \-q ", " \-\^\-quiet ", " \-\^\-silent
  • lib/posix/regex.h

    diff -urN grep-2.5.1a.orig/lib/posix/regex.h grep-2.5.1a/lib/posix/regex.h
    old new  
    109109   If not set, \{, \}, {, and } are literals.  */
    110110#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
    111111
     112/* If this bit is set, then ignore case when matching.
     113   If not set, then case is significant.  */
     114#define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1)
     115
    112116/* If this bit is set, +, ? and | aren't recognized as operators.
    113117   If not set, they are.  */
    114118#define RE_LIMITED_OPS (RE_INTERVALS << 1)
  • grep-2.5.1a

    diff -urN grep-2.5.1a.orig/src/dfa.c grep-2.5.1a/src/dfa.c
    old new  
    414414
    415415/* This function fetch a wide character, and update cur_mb_len,
    416416   used only if the current locale is a multibyte environment.  */
    417 static wchar_t
     417static wint_t
    418418fetch_wc (char const *eoferr)
    419419{
    420420  wchar_t wc;
     
    423423      if (eoferr != 0)
    424424        dfaerror (eoferr);
    425425      else
    426         return -1;
     426        return WEOF;
    427427    }
    428428
    429429  cur_mb_len = mbrtowc(&wc, lexptr, lexleft, &mbs);
     
    459459static void
    460460parse_bracket_exp_mb ()
    461461{
    462   wchar_t wc, wc1, wc2;
     462  wint_t wc, wc1, wc2;
    463463
    464464  /* Work area to build a mb_char_classes.  */
    465465  struct mb_char_classes *work_mbc;
     
    496496    work_mbc->invert = 0;
    497497  do
    498498    {
    499       wc1 = -1; /* mark wc1 is not initialized".  */
     499      wc1 = WEOF; /* mark wc1 is not initialized".  */
    500500
    501501      /* Note that if we're looking at some other [:...:] construct,
    502502         we just treat it as a bunch of ordinary characters.  We can do
     
    586586                      work_mbc->coll_elems[work_mbc->ncoll_elems++] = elem;
    587587                    }
    588588                }
    589               wc = -1;
     589              wc1 = wc = WEOF;
    590590            }
    591591          else
    592592            /* We treat '[' as a normal character here.  */
     
    600600            wc = fetch_wc(("Unbalanced ["));
    601601        }
    602602
    603       if (wc1 == -1)
     603      if (wc1 == WEOF)
    604604        wc1 = fetch_wc(_("Unbalanced ["));
    605605
    606606      if (wc1 == L'-')
     
    630630            }
    631631          REALLOC_IF_NECESSARY(work_mbc->range_sts, wchar_t,
    632632                               range_sts_al, work_mbc->nranges + 1);
    633           work_mbc->range_sts[work_mbc->nranges] = wc;
     633          work_mbc->range_sts[work_mbc->nranges] = (wchar_t)wc;
    634634          REALLOC_IF_NECESSARY(work_mbc->range_ends, wchar_t,
    635635                               range_ends_al, work_mbc->nranges + 1);
    636           work_mbc->range_ends[work_mbc->nranges++] = wc2;
     636          work_mbc->range_ends[work_mbc->nranges++] = (wchar_t)wc2;
    637637        }
    638       else if (wc != -1)
     638      else if (wc != WEOF)
    639639        /* build normal characters.  */
    640640        {
    641641          REALLOC_IF_NECESSARY(work_mbc->chars, wchar_t, chars_al,
    642642                               work_mbc->nchars + 1);
    643           work_mbc->chars[work_mbc->nchars++] = wc;
     643          work_mbc->chars[work_mbc->nchars++] = (wchar_t)wc;
    644644        }
    645645    }
    646646  while ((wc = wc1) != L']');
     
    25522552    }
    25532553
    25542554  /* match with a character?  */
     2555  if (case_fold)
     2556    wc = towlower (wc);
    25552557  for (i = 0; i<work_mbc->nchars; i++)
    25562558    {
    25572559      if (wc == work_mbc->chars[i])
  • src/grep.c

    diff -urN grep-2.5.1a.orig/src/grep.c grep-2.5.1a/src/grep.c
    old new  
    3030# include <sys/time.h>
    3131# include <sys/resource.h>
    3232#endif
     33#if defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H && defined HAVE_MBRTOWC
     34/* We can handle multibyte string.  */
     35# define MBS_SUPPORT
     36# include <wchar.h>
     37# include <wctype.h>
     38#endif
    3339#include <stdio.h>
    3440#include "system.h"
    3541#include "getopt.h"
     
    558564    {
    559565      size_t match_size;
    560566      size_t match_offset;
    561       if(match_icase)
    562         {
    563           /* Yuck, this is tricky */
    564           char *buf = (char*) xmalloc (lim - beg);
    565           char *ibeg = buf;
    566           char *ilim = ibeg + (lim - beg);
    567           int i;
    568           for (i = 0; i < lim - beg; i++)
    569             ibeg[i] = tolower (beg[i]);
    570           while ((match_offset = (*execute) (ibeg, ilim-ibeg, &match_size, 1))
    571                  != (size_t) -1)
    572             {
    573               char const *b = beg + match_offset;
    574               if (b == lim)
    575                 break;
    576               fwrite (beg, sizeof (char), match_offset, stdout);
    577               printf ("\33[%sm", grep_color);
    578               fwrite (b, sizeof (char), match_size, stdout);
    579               fputs ("\33[00m", stdout);
    580               beg = b + match_size;
    581               ibeg = ibeg + match_offset + match_size;
    582             }
    583           fwrite (beg, 1, lim - beg, stdout);
    584           free (buf);
    585           lastout = lim;
    586           return;
    587         }
    588567      while (lim-beg && (match_offset = (*execute) (beg, lim - beg, &match_size, 1))
    589568             != (size_t) -1)
    590569        {
     
    601580          fputs ("\33[00m", stdout);
    602581          beg = b + match_size;
    603582        }
     583      fputs ("\33[K", stdout);
    604584    }
    605585  fwrite (beg, 1, lim - beg, stdout);
    606586  if (ferror (stdout))
     
    16971677  if (!install_matcher (matcher) && !install_matcher ("default"))
    16981678    abort ();
    16991679
     1680#ifdef MBS_SUPPORT
     1681  if (MB_CUR_MAX != 1 && match_icase)
     1682    {
     1683      wchar_t wc;
     1684      mbstate_t cur_state, prev_state;
     1685      int i, len = strlen(keys);
     1686
     1687      memset(&cur_state, 0, sizeof(mbstate_t));
     1688      for (i = 0; i <= len ;)
     1689        {
     1690          size_t mbclen;
     1691          mbclen = mbrtowc(&wc, keys + i, len - i, &cur_state);
     1692          if (mbclen == (size_t) -1 || mbclen == (size_t) -2 || mbclen == 0)
     1693            {
     1694              /* An invalid sequence, or a truncated multibyte character.
     1695                 We treat it as a singlebyte character.  */
     1696              mbclen = 1;
     1697            }
     1698          else
     1699            {
     1700              if (iswupper((wint_t)wc))
     1701                {
     1702                  wc = towlower((wint_t)wc);
     1703                  wcrtomb(keys + i, wc, &cur_state);
     1704                }
     1705            }
     1706          i += mbclen;
     1707        }
     1708    }
     1709#endif /* MBS_SUPPORT */
     1710
    17001711  (*compile)(keys, keycc);
    17011712
    17021713  if ((argc - optind > 1 && !no_filenames) || with_filenames)
  • src/search.c

    diff -urN grep-2.5.1a.orig/src/search.c grep-2.5.1a/src/search.c
    old new  
    1818
    1919/* Written August 1992 by Mike Haertel. */
    2020
     21#ifndef _GNU_SOURCE
     22# define _GNU_SOURCE 1
     23#endif
    2124#ifdef HAVE_CONFIG_H
    2225# include <config.h>
    2326#endif
     27#include <assert.h>
    2428#include <sys/types.h>
    2529#if defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H && defined HAVE_MBRTOWC
    2630/* We can handle multibyte string.  */
     
    3135
    3236#include "system.h"
    3337#include "grep.h"
    34 #include "regex.h"
     38#include <regex.h>
    3539#include "dfa.h"
    3640#include "kwset.h"
    3741#include "error.h"
     
    3943#ifdef HAVE_LIBPCRE
    4044# include <pcre.h>
    4145#endif
     46#ifdef HAVE_LANGINFO_CODESET
     47# include <langinfo.h>
     48#endif
    4249
    4350#define NCHAR (UCHAR_MAX + 1)
    4451
     
    7077   call the regexp matcher at all. */
    7178static int kwset_exact_matches;
    7279
    73 #if defined(MBS_SUPPORT)
    74 static char* check_multibyte_string PARAMS ((char const *buf, size_t size));
    75 #endif
     80/* UTF-8 encoding allows some optimizations that we can't otherwise
     81   assume in a multibyte encoding. */
     82static int using_utf8;
     83
    7684static void kwsinit PARAMS ((void));
    7785static void kwsmusts PARAMS ((void));
    7886static void Gcompile PARAMS ((char const *, size_t));
     
    8492static size_t Pexecute PARAMS ((char const *, size_t, size_t *, int));
    8593
    8694void
     95check_utf8 (void)
     96{
     97#ifdef HAVE_LANGINFO_CODESET
     98  if (strcmp (nl_langinfo (CODESET), "UTF-8") == 0)
     99    using_utf8 = 1;
     100#endif
     101}
     102
     103void
    87104dfaerror (char const *mesg)
    88105{
    89106  error (2, 0, mesg);
     
    141158    }
    142159}
    143160
    144 #ifdef MBS_SUPPORT
    145 /* This function allocate the array which correspond to "buf".
    146    Then this check multibyte string and mark on the positions which
    147    are not singlebyte character nor the first byte of a multibyte
    148    character.  Caller must free the array.  */
    149 static char*
    150 check_multibyte_string(char const *buf, size_t size)
    151 {
    152   char *mb_properties = malloc(size);
    153   mbstate_t cur_state;
    154   int i;
    155   memset(&cur_state, 0, sizeof(mbstate_t));
    156   memset(mb_properties, 0, sizeof(char)*size);
    157   for (i = 0; i < size ;)
    158     {
    159       size_t mbclen;
    160       mbclen = mbrlen(buf + i, size - i, &cur_state);
    161 
    162       if (mbclen == (size_t) -1 || mbclen == (size_t) -2 || mbclen == 0)
    163         {
    164           /* An invalid sequence, or a truncated multibyte character.
    165              We treat it as a singlebyte character.  */
    166           mbclen = 1;
    167         }
    168       mb_properties[i] = mbclen;
    169       i += mbclen;
    170     }
    171 
    172   return mb_properties;
    173 }
    174 #endif
    175 
    176161static void
    177162Gcompile (char const *pattern, size_t size)
    178163{
     
    181166  size_t total = size;
    182167  char const *motif = pattern;
    183168
    184   re_set_syntax (RE_SYNTAX_GREP | RE_HAT_LISTS_NOT_NEWLINE);
     169  check_utf8 ();
     170  re_set_syntax (RE_SYNTAX_GREP | RE_HAT_LISTS_NOT_NEWLINE | (match_icase ? RE_ICASE : 0));
    185171  dfasyntax (RE_SYNTAX_GREP | RE_HAT_LISTS_NOT_NEWLINE, match_icase, eolbyte);
    186172
    187173  /* For GNU regex compiler we have to pass the patterns separately to detect
     
    233219      static char const line_end[] = "\\)$";
    234220      static char const word_beg[] = "\\(^\\|[^[:alnum:]_]\\)\\(";
    235221      static char const word_end[] = "\\)\\([^[:alnum:]_]\\|$\\)";
    236       char *n = malloc (sizeof word_beg - 1 + size + sizeof word_end);
     222      char *n = xmalloc (sizeof word_beg - 1 + size + sizeof word_end);
    237223      size_t i;
    238224      strcpy (n, match_lines ? line_beg : word_beg);
    239225      i = strlen (n);
     
    257243  size_t total = size;
    258244  char const *motif = pattern;
    259245
     246  check_utf8 ();
    260247  if (strcmp (matcher, "awk") == 0)
    261248    {
    262       re_set_syntax (RE_SYNTAX_AWK);
     249      re_set_syntax (RE_SYNTAX_AWK | (match_icase ? RE_ICASE : 0));
    263250      dfasyntax (RE_SYNTAX_AWK, match_icase, eolbyte);
    264251    }
    265252  else
    266253    {
    267       re_set_syntax (RE_SYNTAX_POSIX_EGREP);
     254      re_set_syntax (RE_SYNTAX_POSIX_EGREP | (match_icase ? RE_ICASE : 0));
    268255      dfasyntax (RE_SYNTAX_POSIX_EGREP, match_icase, eolbyte);
    269256    }
    270257
     
    316303      static char const line_end[] = ")$";
    317304      static char const word_beg[] = "(^|[^[:alnum:]_])(";
    318305      static char const word_end[] = ")([^[:alnum:]_]|$)";
    319       char *n = malloc (sizeof word_beg - 1 + size + sizeof word_end);
     306      char *n = xmalloc (sizeof word_beg - 1 + size + sizeof word_end);
    320307      size_t i;
    321308      strcpy (n, match_lines ? line_beg : word_beg);
    322309      i = strlen(n);
     
    339326  char eol = eolbyte;
    340327  int backref, start, len;
    341328  struct kwsmatch kwsm;
    342   size_t i;
     329  size_t i, ret_val;
     330  static int use_dfa;
     331  static int use_dfa_checked = 0;
    343332#ifdef MBS_SUPPORT
    344   char *mb_properties = NULL;
     333  const char *last_char = NULL;
     334  int mb_cur_max = MB_CUR_MAX;
     335  mbstate_t mbs;
     336  memset (&mbs, '\0', sizeof (mbstate_t));
    345337#endif /* MBS_SUPPORT */
    346338
     339  if (!use_dfa_checked)
     340    {
     341      char *grep_use_dfa = getenv ("GREP_USE_DFA");
     342      if (!grep_use_dfa)
     343        {
    347344#ifdef MBS_SUPPORT
    348   if (MB_CUR_MAX > 1 && kwset)
    349     mb_properties = check_multibyte_string(buf, size);
     345          /* Turn off DFA when processing multibyte input. */
     346          use_dfa = (MB_CUR_MAX == 1);
     347#else
     348          use_dfa = 1;
    350349#endif /* MBS_SUPPORT */
     350        }
     351      else
     352        {
     353          use_dfa = atoi (grep_use_dfa);
     354        }
     355
     356      use_dfa_checked = 1;
     357    }
    351358
    352359  buflim = buf + size;
    353360
     
    358365          if (kwset)
    359366            {
    360367              /* Find a possible match using the KWset matcher. */
    361               size_t offset = kwsexec (kwset, beg, buflim - beg, &kwsm);
     368#ifdef MBS_SUPPORT
     369              size_t bytes_left = 0;
     370#endif /* MBS_SUPPORT */
     371              size_t offset;
     372#ifdef MBS_SUPPORT
     373              /* kwsexec doesn't work with match_icase and multibyte input. */
     374              if (match_icase && mb_cur_max > 1)
     375                /* Avoid kwset */
     376                offset = 0;
     377              else
     378#endif /* MBS_SUPPORT */
     379              offset = kwsexec (kwset, beg, buflim - beg, &kwsm);
    362380              if (offset == (size_t) -1)
    363                 {
     381                goto failure;
    364382#ifdef MBS_SUPPORT
    365                   if (MB_CUR_MAX > 1)
    366                     free(mb_properties);
    367 #endif
    368                   return (size_t)-1;
     383              if (mb_cur_max > 1 && !using_utf8)
     384                {
     385                  bytes_left = offset;
     386                  while (bytes_left)
     387                    {
     388                      size_t mlen = mbrlen (beg, bytes_left, &mbs);
     389
     390                      last_char = beg;
     391                      if (mlen == (size_t) -1 || mlen == 0)
     392                        {
     393                          /* Incomplete character: treat as single-byte. */
     394                          memset (&mbs, '\0', sizeof (mbstate_t));
     395                          beg++;
     396                          bytes_left--;
     397                          continue;
     398                        }
     399
     400                      if (mlen == (size_t) -2)
     401                        /* Offset points inside multibyte character:
     402                         * no good. */
     403                        break;
     404
     405                      beg += mlen;
     406                      bytes_left -= mlen;
     407                    }
    369408                }
     409              else
     410#endif /* MBS_SUPPORT */
    370411              beg += offset;
    371412              /* Narrow down to the line containing the candidate, and
    372413                 run it through DFA. */
    373414              end = memchr(beg, eol, buflim - beg);
    374415              end++;
    375416#ifdef MBS_SUPPORT
    376               if (MB_CUR_MAX > 1 && mb_properties[beg - buf] == 0)
     417              if (mb_cur_max > 1 && bytes_left)
    377418                continue;
    378 #endif
     419#endif /* MBS_SUPPORT */
    379420              while (beg > buf && beg[-1] != eol)
    380421                --beg;
    381               if (kwsm.index < kwset_exact_matches)
    382                 goto success;
    383               if (dfaexec (&dfa, beg, end - beg, &backref) == (size_t) -1)
     422              if (
     423#ifdef MBS_SUPPORT
     424                  !(match_icase && mb_cur_max > 1) &&
     425#endif /* MBS_SUPPORT */
     426                  (kwsm.index < kwset_exact_matches))
     427                goto success_in_beg_and_end;
     428              if (use_dfa &&
     429                  dfaexec (&dfa, beg, end - beg, &backref) == (size_t) -1)
    384430                continue;
    385431            }
    386432          else
    387433            {
    388434              /* No good fixed strings; start with DFA. */
    389               size_t offset = dfaexec (&dfa, beg, buflim - beg, &backref);
     435#ifdef MBS_SUPPORT
     436              size_t bytes_left = 0;
     437#endif /* MBS_SUPPORT */
     438              size_t offset = 0;
     439              if (use_dfa)
     440                offset = dfaexec (&dfa, beg, buflim - beg, &backref);
    390441              if (offset == (size_t) -1)
    391442                break;
    392443              /* Narrow down to the line we've found. */
     444#ifdef MBS_SUPPORT
     445              if (mb_cur_max > 1 && !using_utf8)
     446                {
     447                  bytes_left = offset;
     448                  while (bytes_left)
     449                    {
     450                      size_t mlen = mbrlen (beg, bytes_left, &mbs);
     451
     452                      last_char = beg;
     453                      if (mlen == (size_t) -1 || mlen == 0)
     454                        {
     455                          /* Incomplete character: treat as single-byte. */
     456                          memset (&mbs, '\0', sizeof (mbstate_t));
     457                          beg++;
     458                          bytes_left--;
     459                          continue;
     460                        }
     461
     462                      if (mlen == (size_t) -2)
     463                        /* Offset points inside multibyte character:
     464                         * no good. */
     465                        break;
     466
     467                      beg += mlen;
     468                      bytes_left -= mlen;
     469                    }
     470                }
     471              else
     472#endif /* MBS_SUPPORT */
    393473              beg += offset;
    394474              end = memchr (beg, eol, buflim - beg);
    395475              end++;
     476#ifdef MBS_SUPPORT
     477              if (mb_cur_max > 1 && bytes_left)
     478                continue;
     479#endif /* MBS_SUPPORT */
    396480              while (beg > buf && beg[-1] != eol)
    397481                --beg;
    398482            }
    399483          /* Successful, no backreferences encountered! */
    400           if (!backref)
    401             goto success;
     484          if (use_dfa && !backref)
     485            goto success_in_beg_and_end;
    402486        }
    403487      else
    404488        end = beg + size;
     
    413497                                       end - beg - 1, &(patterns[i].regs))))
    414498            {
    415499              len = patterns[i].regs.end[0] - start;
    416               if (exact)
    417                 {
    418                   *match_size = len;
    419                   return start;
    420                 }
     500              if (exact && !match_words)
     501                goto success_in_start_and_len;
    421502              if ((!match_lines && !match_words)
    422503                  || (match_lines && len == end - beg - 1))
    423                 goto success;
     504                goto success_in_beg_and_end;
    424505              /* If -w, check if the match aligns with word boundaries.
    425506                 We do this iteratively because:
    426507                 (a) the line may contain more than one occurence of the
     
    431512              if (match_words)
    432513                while (start >= 0)
    433514                  {
    434                     if ((start == 0 || !WCHAR ((unsigned char) beg[start - 1]))
    435                         && (len == end - beg - 1
    436                             || !WCHAR ((unsigned char) beg[start + len])))
    437                       goto success;
     515                    int lword_match = 0;
     516                    if (start == 0)
     517                      lword_match = 1;
     518                    else
     519                      {
     520                        assert (start > 0);
     521#ifdef MBS_SUPPORT
     522                        if (mb_cur_max > 1)
     523                          {
     524                            const char *s;
     525                            int mr;
     526                            wchar_t pwc;
     527
     528                            if (using_utf8)
     529                              {
     530                                s = beg + start - 1;
     531                                while (s > buf
     532                                       && (unsigned char) *s >= 0x80
     533                                       && (unsigned char) *s <= 0xbf)
     534                                  --s;
     535                              }
     536                            else
     537                              s = last_char;
     538                            mr = mbtowc (&pwc, s, beg + start - s);
     539                            if (mr <= 0)
     540                              {
     541                                memset (&mbs, '\0', sizeof (mbstate_t));
     542                                lword_match = 1;
     543                              }
     544                            else if (!(iswalnum (pwc) || pwc == L'_')
     545                                     && mr == (int) (beg + start - s))
     546                              lword_match = 1;
     547                          }
     548                        else
     549#endif /* MBS_SUPPORT */
     550                        if (!WCHAR ((unsigned char) beg[start - 1]))
     551                          lword_match = 1;
     552                      }
     553
     554                    if (lword_match)
     555                      {
     556                        int rword_match = 0;
     557                        if (start + len == end - beg - 1)
     558                          rword_match = 1;
     559                        else
     560                          {
     561#ifdef MBS_SUPPORT
     562                            if (mb_cur_max > 1)
     563                              {
     564                                wchar_t nwc;
     565                                int mr;
     566
     567                                mr = mbtowc (&nwc, beg + start + len,
     568                                             end - beg - start - len - 1);
     569                                if (mr <= 0)
     570                                  {
     571                                    memset (&mbs, '\0', sizeof (mbstate_t));
     572                                    rword_match = 1;
     573                                  }
     574                                else if (!iswalnum (nwc) && nwc != L'_')
     575                                  rword_match = 1;
     576                              }
     577                            else
     578#endif /* MBS_SUPPORT */
     579                            if (!WCHAR ((unsigned char) beg[start + len]))
     580                              rword_match = 1;
     581                          }
     582
     583                        if (rword_match)
     584                          {
     585                            if (!exact)
     586                              /* Returns the whole line. */
     587                              goto success_in_beg_and_end;
     588                            else
     589                              /* Returns just this word match. */
     590                              goto success_in_start_and_len;
     591                          }
     592                      }
    438593                    if (len > 0)
    439594                      {
    440595                        /* Try a shorter length anchored at the same place. */
     
    461616            }
    462617        } /* for Regex patterns.  */
    463618    } /* for (beg = end ..) */
    464 #ifdef MBS_SUPPORT
    465   if (MB_CUR_MAX > 1 && mb_properties)
    466     free (mb_properties);
    467 #endif /* MBS_SUPPORT */
     619
     620 failure:
    468621  return (size_t) -1;
    469622
    470  success:
    471 #ifdef MBS_SUPPORT
    472   if (MB_CUR_MAX > 1 && mb_properties)
    473     free (mb_properties);
    474 #endif /* MBS_SUPPORT */
    475   *match_size = end - beg;
    476   return beg - buf;
     623 success_in_beg_and_end:
     624  len = end - beg;
     625  start = beg - buf;
     626  /* FALLTHROUGH */
     627
     628 success_in_start_and_len:
     629  *match_size = len;
     630  return start;
    477631}
    478632
     633#ifdef MBS_SUPPORT
     634static int f_i_multibyte; /* whether we're using the new -Fi MB method */
     635static struct
     636{
     637  wchar_t **patterns;
     638  size_t count, maxlen;
     639  unsigned char *match;
     640} Fimb;
     641#endif
     642
    479643static void
    480644Fcompile (char const *pattern, size_t size)
    481645{
     646  int mb_cur_max = MB_CUR_MAX;
    482647  char const *beg, *lim, *err;
    483648
     649  check_utf8 ();
     650#ifdef MBS_SUPPORT
     651  /* Support -F -i for UTF-8 input. */
     652  if (match_icase && mb_cur_max > 1)
     653    {
     654      mbstate_t mbs;
     655      wchar_t *wcpattern = xmalloc ((size + 1) * sizeof (wchar_t));
     656      const char *patternend = pattern;
     657      size_t wcsize;
     658      kwset_t fimb_kwset = NULL;
     659      char *starts = NULL;
     660      wchar_t *wcbeg, *wclim;
     661      size_t allocated = 0;
     662
     663      memset (&mbs, '\0', sizeof (mbs));
     664# ifdef __GNU_LIBRARY__
     665      wcsize = mbsnrtowcs (wcpattern, &patternend, size, size, &mbs);
     666      if (patternend != pattern + size)
     667        wcsize = (size_t) -1;
     668# else
     669      {
     670        char *patterncopy = xmalloc (size + 1);
     671
     672        memcpy (patterncopy, pattern, size);
     673        patterncopy[size] = '\0';
     674        patternend = patterncopy;
     675        wcsize = mbsrtowcs (wcpattern, &patternend, size, &mbs);
     676        if (patternend != patterncopy + size)
     677          wcsize = (size_t) -1;
     678        free (patterncopy);
     679      }
     680# endif
     681      if (wcsize + 2 <= 2)
     682        {
     683fimb_fail:
     684          free (wcpattern);
     685          free (starts);
     686          if (fimb_kwset)
     687            kwsfree (fimb_kwset);
     688          free (Fimb.patterns);
     689          Fimb.patterns = NULL;
     690        }
     691      else
     692        {
     693          if (!(fimb_kwset = kwsalloc (NULL)))
     694            error (2, 0, _("memory exhausted"));
     695
     696          starts = xmalloc (mb_cur_max * 3);
     697          wcbeg = wcpattern;
     698          do
     699            {
     700              int i;
     701              size_t wclen;
     702
     703              if (Fimb.count >= allocated)
     704                {
     705                  if (allocated == 0)
     706                    allocated = 128;
     707                  else
     708                    allocated *= 2;
     709                  Fimb.patterns = xrealloc (Fimb.patterns,
     710                                            sizeof (wchar_t *) * allocated);
     711                }
     712              Fimb.patterns[Fimb.count++] = wcbeg;
     713              for (wclim = wcbeg;
     714                   wclim < wcpattern + wcsize && *wclim != L'\n'; ++wclim)
     715                *wclim = towlower (*wclim);
     716              *wclim = L'\0';
     717              wclen = wclim - wcbeg;
     718              if (wclen > Fimb.maxlen)
     719                Fimb.maxlen = wclen;
     720              if (wclen > 3)
     721                wclen = 3;
     722              if (wclen == 0)
     723                {
     724                  if ((err = kwsincr (fimb_kwset, "", 0)) != 0)
     725                    error (2, 0, err);
     726                }
     727              else
     728                for (i = 0; i < (1 << wclen); i++)
     729                  {
     730                    char *p = starts;
     731                    int j, k;
     732
     733                    for (j = 0; j < wclen; ++j)
     734                      {
     735                        wchar_t wc = wcbeg[j];
     736                        if (i & (1 << j))
     737                          {
     738                            wc = towupper (wc);
     739                            if (wc == wcbeg[j])
     740                              continue;
     741                          }
     742                        k = wctomb (p, wc);
     743                        if (k <= 0)
     744                          goto fimb_fail;
     745                        p += k;
     746                      }
     747                    if ((err = kwsincr (fimb_kwset, starts, p - starts)) != 0)
     748                      error (2, 0, err);
     749                  }
     750              if (wclim < wcpattern + wcsize)
     751                ++wclim;
     752              wcbeg = wclim;
     753            }
     754          while (wcbeg < wcpattern + wcsize);
     755          f_i_multibyte = 1;
     756          kwset = fimb_kwset;
     757          free (starts);
     758          Fimb.match = xmalloc (Fimb.count);
     759          if ((err = kwsprep (kwset)) != 0)
     760            error (2, 0, err);
     761          return;
     762        }
     763    }
     764#endif /* MBS_SUPPORT */
     765
     766
    484767  kwsinit ();
    485768  beg = pattern;
    486769  do
     
    499782    error (2, 0, err);
    500783}
    501784
     785#ifdef MBS_SUPPORT
     786static int
     787Fimbexec (const char *buf, size_t size, size_t *plen, int exact)
     788{
     789  size_t len, letter, i;
     790  int ret = -1;
     791  mbstate_t mbs;
     792  wchar_t wc;
     793  int patterns_left;
     794
     795  assert (match_icase && f_i_multibyte == 1);
     796  assert (MB_CUR_MAX > 1);
     797
     798  memset (&mbs, '\0', sizeof (mbs));
     799  memset (Fimb.match, '\1', Fimb.count);
     800  letter = len = 0;
     801  patterns_left = 1;
     802  while (patterns_left && len <= size)
     803    {
     804      size_t c;
     805
     806      patterns_left = 0;
     807      if (len < size)
     808        {
     809          c = mbrtowc (&wc, buf + len, size - len, &mbs);
     810          if (c + 2 <= 2)
     811            return ret;
     812
     813          wc = towlower (wc);
     814        }
     815      else
     816        {
     817          c = 1;
     818          wc = L'\0';
     819        }
     820
     821      for (i = 0; i < Fimb.count; i++)
     822        {
     823          if (Fimb.match[i])
     824            {
     825              if (Fimb.patterns[i][letter] == L'\0')
     826                {
     827                  /* Found a match. */
     828                  *plen = len;
     829                  if (!exact && !match_words)
     830                    return 0;
     831                  else
     832                    {
     833                      /* For -w or exact look for longest match.  */
     834                      ret = 0;
     835                      Fimb.match[i] = '\0';
     836                      continue;
     837                    }
     838                }
     839
     840              if (Fimb.patterns[i][letter] == wc)
     841                patterns_left = 1;
     842              else
     843                Fimb.match[i] = '\0';
     844            }
     845        }
     846
     847      len += c;
     848      letter++;
     849    }
     850
     851  return ret;
     852}
     853#endif /* MBS_SUPPORT */
     854
    502855static size_t
    503856Fexecute (char const *buf, size_t size, size_t *match_size, int exact)
    504857{
     
    506859  register size_t len;
    507860  char eol = eolbyte;
    508861  struct kwsmatch kwsmatch;
     862  size_t ret_val;
    509863#ifdef MBS_SUPPORT
    510   char *mb_properties;
    511   if (MB_CUR_MAX > 1)
    512     mb_properties = check_multibyte_string (buf, size);
     864  int mb_cur_max = MB_CUR_MAX;
     865  mbstate_t mbs;
     866  memset (&mbs, '\0', sizeof (mbstate_t));
     867  const char *last_char = NULL;
    513868#endif /* MBS_SUPPORT */
    514869
    515870  for (beg = buf; beg <= buf + size; ++beg)
    516871    {
    517       size_t offset = kwsexec (kwset, beg, buf + size - beg, &kwsmatch);
     872      size_t offset;
     873      offset = kwsexec (kwset, beg, buf + size - beg, &kwsmatch);
     874
    518875      if (offset == (size_t) -1)
    519         {
     876        goto failure;
    520877#ifdef MBS_SUPPORT
    521           if (MB_CUR_MAX > 1)
    522             free(mb_properties);
    523 #endif /* MBS_SUPPORT */
    524           return offset;
     878      if (mb_cur_max > 1 && !using_utf8)
     879        {
     880          size_t bytes_left = offset;
     881          while (bytes_left)
     882            {
     883              size_t mlen = mbrlen (beg, bytes_left, &mbs);
     884
     885              last_char = beg;
     886              if (mlen == (size_t) -1 || mlen == 0)
     887                {
     888                  /* Incomplete character: treat as single-byte. */
     889                  memset (&mbs, '\0', sizeof (mbstate_t));
     890                  beg++;
     891                  bytes_left--;
     892                  continue;
     893                }
     894
     895              if (mlen == (size_t) -2)
     896                /* Offset points inside multibyte character: no good. */
     897                break;
     898
     899              beg += mlen;
     900              bytes_left -= mlen;
     901            }
     902
     903          if (bytes_left)
     904            continue;
    525905        }
    526 #ifdef MBS_SUPPORT
    527       if (MB_CUR_MAX > 1 && mb_properties[offset+beg-buf] == 0)
    528         continue; /* It is a part of multibyte character.  */
     906      else
    529907#endif /* MBS_SUPPORT */
    530908      beg += offset;
    531       len = kwsmatch.size[0];
    532       if (exact)
    533         {
    534           *match_size = len;
    535909#ifdef MBS_SUPPORT
    536           if (MB_CUR_MAX > 1)
    537             free (mb_properties);
     910      /* For f_i_multibyte, the string at beg now matches first 3 chars of
     911         one of the search strings (less if there are shorter search strings).
     912         See if this is a real match.  */
     913      if (f_i_multibyte
     914          && Fimbexec (beg, buf + size - beg, &kwsmatch.size[0], exact))
     915        goto next_char;
    538916#endif /* MBS_SUPPORT */
    539           return beg - buf;
    540         }
     917      len = kwsmatch.size[0];
     918      if (exact && !match_words)
     919        goto success_in_beg_and_len;
    541920      if (match_lines)
    542921        {
    543922          if (beg > buf && beg[-1] != eol)
    544             continue;
     923            goto next_char;
    545924          if (beg + len < buf + size && beg[len] != eol)
    546             continue;
     925            goto next_char;
    547926          goto success;
    548927        }
    549928      else if (match_words)
    550         for (try = beg; len; )
    551           {
    552             if (try > buf && WCHAR((unsigned char) try[-1]))
    553               break;
    554             if (try + len < buf + size && WCHAR((unsigned char) try[len]))
    555               {
    556                 offset = kwsexec (kwset, beg, --len, &kwsmatch);
    557                 if (offset == (size_t) -1)
    558                   {
     929        {
     930          while (len)
     931            {
     932              int word_match = 0;
     933              if (beg > buf)
     934                {
    559935#ifdef MBS_SUPPORT
    560                     if (MB_CUR_MAX > 1)
    561                       free (mb_properties);
     936                  if (mb_cur_max > 1)
     937                    {
     938                      const char *s;
     939                      int mr;
     940                      wchar_t pwc;
     941
     942                      if (using_utf8)
     943                        {
     944                          s = beg - 1;
     945                          while (s > buf
     946                                 && (unsigned char) *s >= 0x80
     947                                 && (unsigned char) *s <= 0xbf)
     948                            --s;
     949                        }
     950                      else
     951                        s = last_char;
     952                      mr = mbtowc (&pwc, s, beg - s);
     953                      if (mr <= 0)
     954                        memset (&mbs, '\0', sizeof (mbstate_t));
     955                      else if ((iswalnum (pwc) || pwc == L'_')
     956                               && mr == (int) (beg - s))
     957                        goto next_char;
     958                    }
     959                  else
    562960#endif /* MBS_SUPPORT */
    563                     return offset;
    564                   }
    565                 try = beg + offset;
    566                 len = kwsmatch.size[0];
    567               }
    568             else
    569               goto success;
    570           }
     961                  if (WCHAR ((unsigned char) beg[-1]))
     962                    goto next_char;
     963                }
     964#ifdef MBS_SUPPORT
     965              if (mb_cur_max > 1)
     966                {
     967                  wchar_t nwc;
     968                  int mr;
     969
     970                  mr = mbtowc (&nwc, beg + len, buf + size - beg - len);
     971                  if (mr <= 0)
     972                    {
     973                      memset (&mbs, '\0', sizeof (mbstate_t));
     974                      word_match = 1;
     975                    }
     976                  else if (!iswalnum (nwc) && nwc != L'_')
     977                    word_match = 1;
     978                }
     979              else
     980#endif /* MBS_SUPPORT */
     981                if (beg + len >= buf + size || !WCHAR ((unsigned char) beg[len]))
     982                  word_match = 1;
     983              if (word_match)
     984                {
     985                  if (!exact)
     986                    /* Returns the whole line now we know there's a word match. */
     987                    goto success;
     988                  else
     989                    /* Returns just this word match. */
     990                    goto success_in_beg_and_len;
     991                }
     992              if (len > 0)
     993                {
     994                  /* Try a shorter length anchored at the same place. */
     995                  --len;
     996                  offset = kwsexec (kwset, beg, len, &kwsmatch);
     997
     998                  if (offset == -1)
     999                    goto next_char; /* Try a different anchor. */
     1000#ifdef MBS_SUPPORT
     1001                  if (mb_cur_max > 1 && !using_utf8)
     1002                    {
     1003                      size_t bytes_left = offset;
     1004                      while (bytes_left)
     1005                        {
     1006                          size_t mlen = mbrlen (beg, bytes_left, &mbs);
     1007
     1008                          last_char = beg;
     1009                          if (mlen == (size_t) -1 || mlen == 0)
     1010                            {
     1011                              /* Incomplete character: treat as single-byte. */
     1012                              memset (&mbs, '\0', sizeof (mbstate_t));
     1013                              beg++;
     1014                              bytes_left--;
     1015                              continue;
     1016                            }
     1017
     1018                          if (mlen == (size_t) -2)
     1019                            {
     1020                              /* Offset points inside multibyte character:
     1021                               * no good. */
     1022                              break;
     1023                            }
     1024
     1025                          beg += mlen;
     1026                          bytes_left -= mlen;
     1027                        }
     1028
     1029                      if (bytes_left)
     1030                        {
     1031                          memset (&mbs, '\0', sizeof (mbstate_t));
     1032                          goto next_char; /* Try a different anchor. */
     1033                        }
     1034                    }
     1035                  else
     1036#endif /* MBS_SUPPORT */
     1037                  beg += offset;
     1038#ifdef MBS_SUPPORT
     1039                  /* The string at beg now matches first 3 chars of one of
     1040                     the search strings (less if there are shorter search
     1041                     strings).  See if this is a real match.  */
     1042                  if (f_i_multibyte
     1043                      && Fimbexec (beg, len - offset, &kwsmatch.size[0],
     1044                                   exact))
     1045                    goto next_char;
     1046#endif /* MBS_SUPPORT */
     1047                  len = kwsmatch.size[0];
     1048                }
     1049            }
     1050        }
    5711051      else
    5721052        goto success;
    573     }
    574 
     1053next_char:;
    5751054#ifdef MBS_SUPPORT
    576   if (MB_CUR_MAX > 1)
    577     free (mb_properties);
     1055      /* Advance to next character.  For MB_CUR_MAX == 1 case this is handled
     1056         by ++beg above.  */
     1057      if (mb_cur_max > 1)
     1058        {
     1059          if (using_utf8)
     1060            {
     1061              unsigned char c = *beg;
     1062              if (c >= 0xc2)
     1063                {
     1064                  if (c < 0xe0)
     1065                    ++beg;
     1066                  else if (c < 0xf0)
     1067                    beg += 2;
     1068                  else if (c < 0xf8)
     1069                    beg += 3;
     1070                  else if (c < 0xfc)
     1071                    beg += 4;
     1072                  else if (c < 0xfe)
     1073                    beg += 5;
     1074                }
     1075            }
     1076          else
     1077            {
     1078              size_t l = mbrlen (beg, buf + size - beg, &mbs);
     1079
     1080              last_char = beg;
     1081              if (l + 2 >= 2)
     1082                beg += l - 1;
     1083              else
     1084                memset (&mbs, '\0', sizeof (mbstate_t));
     1085            }
     1086        }
    5781087#endif /* MBS_SUPPORT */
     1088    }
     1089
     1090 failure:
    5791091  return -1;
    5801092
    5811093 success:
     1094#ifdef MBS_SUPPORT
     1095  if (mb_cur_max > 1 && !using_utf8)
     1096    {
     1097      end = beg + len;
     1098      while (end < buf + size)
     1099        {
     1100          size_t mlen = mbrlen (end, buf + size - end, &mbs);
     1101          if (mlen == (size_t) -1 || mlen == (size_t) -2 || mlen == 0)
     1102            {
     1103              memset (&mbs, '\0', sizeof (mbstate_t));
     1104              mlen = 1;
     1105            }
     1106          if (mlen == 1 && *end == eol)
     1107            break;
     1108
     1109          end += mlen;
     1110        }
     1111    }
     1112  else
     1113#endif /* MBS_SUPPORT */
    5821114  end = memchr (beg + len, eol, (buf + size) - (beg + len));
     1115
    5831116  end++;
    5841117  while (buf < beg && beg[-1] != eol)
    5851118    --beg;
    586   *match_size = end - beg;
    587 #ifdef MBS_SUPPORT
    588   if (MB_CUR_MAX > 1)
    589     free (mb_properties);
    590 #endif /* MBS_SUPPORT */
     1119  len = end - beg;
     1120  /* FALLTHROUGH */
     1121
     1122 success_in_beg_and_len:
     1123  *match_size = len;
    5911124  return beg - buf;
    5921125}
    5931126
  • src/search.c.orig

    diff -urN grep-2.5.1a.orig/src/search.c.orig grep-2.5.1a/src/search.c.orig
    old new  
     1/* search.c - searching subroutines using dfa, kwset and regex for grep.
     2   Copyright 1992, 1998, 2000 Free Software Foundation, Inc.
     3
     4   This program is free software; you can redistribute it and/or modify
     5   it under the terms of the GNU General Public License as published by
     6   the Free Software Foundation; either version 2, or (at your option)
     7   any later version.
     8
     9   This program is distributed in the hope that it will be useful,
     10   but WITHOUT ANY WARRANTY; without even the implied warranty of
     11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12   GNU General Public License for more details.
     13
     14   You should have received a copy of the GNU General Public License
     15   along with this program; if not, write to the Free Software
     16   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
     17   02111-1307, USA.  */
     18
     19/* Written August 1992 by Mike Haertel. */
     20
     21#ifdef HAVE_CONFIG_H
     22# include <config.h>
     23#endif
     24#include <sys/types.h>
     25#if defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H && defined HAVE_MBRTOWC
     26/* We can handle multibyte string.  */
     27# define MBS_SUPPORT
     28# include <wchar.h>
     29# include <wctype.h>
     30#endif
     31
     32#include "system.h"
     33#include "grep.h"
     34#include "regex.h"
     35#include "dfa.h"
     36#include "kwset.h"
     37#include "error.h"
     38#include "xalloc.h"
     39#ifdef HAVE_LIBPCRE
     40# include <pcre.h>
     41#endif
     42
     43#define NCHAR (UCHAR_MAX + 1)
     44
     45/* For -w, we also consider _ to be word constituent.  */
     46#define WCHAR(C) (ISALNUM(C) || (C) == '_')
     47
     48/* DFA compiled regexp. */
     49static struct dfa dfa;
     50
     51/* The Regex compiled patterns.  */
     52static struct patterns
     53{
     54  /* Regex compiled regexp. */
     55  struct re_pattern_buffer regexbuf;
     56  struct re_registers regs; /* This is here on account of a BRAIN-DEAD
     57                               Q@#%!# library interface in regex.c.  */
     58} patterns0;
     59
     60struct patterns *patterns;
     61size_t pcount;
     62
     63/* KWset compiled pattern.  For Ecompile and Gcompile, we compile
     64   a list of strings, at least one of which is known to occur in
     65   any string matching the regexp. */
     66static kwset_t kwset;
     67
     68/* Number of compiled fixed strings known to exactly match the regexp.
     69   If kwsexec returns < kwset_exact_matches, then we don't need to
     70   call the regexp matcher at all. */
     71static int kwset_exact_matches;
     72
     73#if defined(MBS_SUPPORT)
     74static char* check_multibyte_string PARAMS ((char const *buf, size_t size));
     75#endif
     76static void kwsinit PARAMS ((void));
     77static void kwsmusts PARAMS ((void));
     78static void Gcompile PARAMS ((char const *, size_t));
     79static void Ecompile PARAMS ((char const *, size_t));
     80static size_t EGexecute PARAMS ((char const *, size_t, size_t *, int ));
     81static void Fcompile PARAMS ((char const *, size_t));
     82static size_t Fexecute PARAMS ((char const *, size_t, size_t *, int));
     83static void Pcompile PARAMS ((char const *, size_t ));
     84static size_t Pexecute PARAMS ((char const *, size_t, size_t *, int));
     85
     86void
     87dfaerror (char const *mesg)
     88{
     89  error (2, 0, mesg);
     90}
     91
     92static void
     93kwsinit (void)
     94{
     95  static char trans[NCHAR];
     96  int i;
     97
     98  if (match_icase)
     99    for (i = 0; i < NCHAR; ++i)
     100      trans[i] = TOLOWER (i);
     101
     102  if (!(kwset = kwsalloc (match_icase ? trans : (char *) 0)))
     103    error (2, 0, _("memory exhausted"));
     104}
     105
     106/* If the DFA turns out to have some set of fixed strings one of
     107   which must occur in the match, then we build a kwset matcher
     108   to find those strings, and thus quickly filter out impossible
     109   matches. */
     110static void
     111kwsmusts (void)
     112{
     113  struct dfamust const *dm;
     114  char const *err;
     115
     116  if (dfa.musts)
     117    {
     118      kwsinit ();
     119      /* First, we compile in the substrings known to be exact
     120         matches.  The kwset matcher will return the index
     121         of the matching string that it chooses. */
     122      for (dm = dfa.musts; dm; dm = dm->next)
     123        {
     124          if (!dm->exact)
     125            continue;
     126          ++kwset_exact_matches;
     127          if ((err = kwsincr (kwset, dm->must, strlen (dm->must))) != 0)
     128            error (2, 0, err);
     129        }
     130      /* Now, we compile the substrings that will require
     131         the use of the regexp matcher.  */
     132      for (dm = dfa.musts; dm; dm = dm->next)
     133        {
     134          if (dm->exact)
     135            continue;
     136          if ((err = kwsincr (kwset, dm->must, strlen (dm->must))) != 0)
     137            error (2, 0, err);
     138        }
     139      if ((err = kwsprep (kwset)) != 0)
     140        error (2, 0, err);
     141    }
     142}
     143
     144#ifdef MBS_SUPPORT
     145/* This function allocate the array which correspond to "buf".
     146   Then this check multibyte string and mark on the positions which
     147   are not singlebyte character nor the first byte of a multibyte
     148   character.  Caller must free the array.  */
     149static char*
     150check_multibyte_string(char const *buf, size_t size)
     151{
     152  char *mb_properties = malloc(size);
     153  mbstate_t cur_state;
     154  int i;
     155  memset(&cur_state, 0, sizeof(mbstate_t));
     156  memset(mb_properties, 0, sizeof(char)*size);
     157  for (i = 0; i < size ;)
     158    {
     159      size_t mbclen;
     160      mbclen = mbrlen(buf + i, size - i, &cur_state);
     161
     162      if (mbclen == (size_t) -1 || mbclen == (size_t) -2 || mbclen == 0)
     163        {
     164          /* An invalid sequence, or a truncated multibyte character.
     165             We treat it as a singlebyte character.  */
     166          mbclen = 1;
     167        }
     168      mb_properties[i] = mbclen;
     169      i += mbclen;
     170    }
     171
     172  return mb_properties;
     173}
     174#endif
     175
     176static void
     177Gcompile (char const *pattern, size_t size)
     178{
     179  const char *err;
     180  char const *sep;
     181  size_t total = size;
     182  char const *motif = pattern;
     183
     184  re_set_syntax (RE_SYNTAX_GREP | RE_HAT_LISTS_NOT_NEWLINE);
     185  dfasyntax (RE_SYNTAX_GREP | RE_HAT_LISTS_NOT_NEWLINE, match_icase, eolbyte);
     186
     187  /* For GNU regex compiler we have to pass the patterns separately to detect
     188     errors like "[\nallo\n]\n".  The patterns here are "[", "allo" and "]"
     189     GNU regex should have raise a syntax error.  The same for backref, where
     190     the backref should have been local to each pattern.  */
     191  do
     192    {
     193      size_t len;
     194      sep = memchr (motif, '\n', total);
     195      if (sep)
     196        {
     197          len = sep - motif;
     198          sep++;
     199          total -= (len + 1);
     200        }
     201      else
     202        {
     203          len = total;
     204          total = 0;
     205        }
     206
     207      patterns = realloc (patterns, (pcount + 1) * sizeof (*patterns));
     208      if (patterns == NULL)
     209        error (2, errno, _("memory exhausted"));
     210
     211      patterns[pcount] = patterns0;
     212
     213      if ((err = re_compile_pattern (motif, len,
     214                                    &(patterns[pcount].regexbuf))) != 0)
     215        error (2, 0, err);
     216      pcount++;
     217
     218      motif = sep;
     219    } while (sep && total != 0);
     220
     221  /* In the match_words and match_lines cases, we use a different pattern
     222     for the DFA matcher that will quickly throw out cases that won't work.
     223     Then if DFA succeeds we do some hairy stuff using the regex matcher
     224     to decide whether the match should really count. */
     225  if (match_words || match_lines)
     226    {
     227      /* In the whole-word case, we use the pattern:
     228         \(^\|[^[:alnum:]_]\)\(userpattern\)\([^[:alnum:]_]|$\).
     229         In the whole-line case, we use the pattern:
     230         ^\(userpattern\)$.  */
     231
     232      static char const line_beg[] = "^\\(";
     233      static char const line_end[] = "\\)$";
     234      static char const word_beg[] = "\\(^\\|[^[:alnum:]_]\\)\\(";
     235      static char const word_end[] = "\\)\\([^[:alnum:]_]\\|$\\)";
     236      char *n = malloc (sizeof word_beg - 1 + size + sizeof word_end);
     237      size_t i;
     238      strcpy (n, match_lines ? line_beg : word_beg);
     239      i = strlen (n);
     240      memcpy (n + i, pattern, size);
     241      i += size;
     242      strcpy (n + i, match_lines ? line_end : word_end);
     243      i += strlen (n + i);
     244      pattern = n;
     245      size = i;
     246    }
     247
     248  dfacomp (pattern, size, &dfa, 1);
     249  kwsmusts ();
     250}
     251
     252static void
     253Ecompile (char const *pattern, size_t size)
     254{
     255  const char *err;
     256  const char *sep;
     257  size_t total = size;
     258  char const *motif = pattern;
     259
     260  if (strcmp (matcher, "awk") == 0)
     261    {
     262      re_set_syntax (RE_SYNTAX_AWK);
     263      dfasyntax (RE_SYNTAX_AWK, match_icase, eolbyte);
     264    }
     265  else
     266    {
     267      re_set_syntax (RE_SYNTAX_POSIX_EGREP);
     268      dfasyntax (RE_SYNTAX_POSIX_EGREP, match_icase, eolbyte);
     269    }
     270
     271  /* For GNU regex compiler we have to pass the patterns separately to detect
     272     errors like "[\nallo\n]\n".  The patterns here are "[", "allo" and "]"
     273     GNU regex should have raise a syntax error.  The same for backref, where
     274     the backref should have been local to each pattern.  */
     275  do
     276    {
     277      size_t len;
     278      sep = memchr (motif, '\n', total);
     279      if (sep)
     280        {
     281          len = sep - motif;
     282          sep++;
     283          total -= (len + 1);
     284        }
     285      else
     286        {
     287          len = total;
     288          total = 0;
     289        }
     290
     291      patterns = realloc (patterns, (pcount + 1) * sizeof (*patterns));
     292      if (patterns == NULL)
     293        error (2, errno, _("memory exhausted"));
     294      patterns[pcount] = patterns0;
     295
     296      if ((err = re_compile_pattern (motif, len,
     297                                    &(patterns[pcount].regexbuf))) != 0)
     298        error (2, 0, err);
     299      pcount++;
     300
     301      motif = sep;
     302    } while (sep && total != 0);
     303
     304  /* In the match_words and match_lines cases, we use a different pattern
     305     for the DFA matcher that will quickly throw out cases that won't work.
     306     Then if DFA succeeds we do some hairy stuff using the regex matcher
     307     to decide whether the match should really count. */
     308  if (match_words || match_lines)
     309    {
     310      /* In the whole-word case, we use the pattern:
     311         (^|[^[:alnum:]_])(userpattern)([^[:alnum:]_]|$).
     312         In the whole-line case, we use the pattern:
     313         ^(userpattern)$.  */
     314
     315      static char const line_beg[] = "^(";
     316      static char const line_end[] = ")$";
     317      static char const word_beg[] = "(^|[^[:alnum:]_])(";
     318      static char const word_end[] = ")([^[:alnum:]_]|$)";
     319      char *n = malloc (sizeof word_beg - 1 + size + sizeof word_end);
     320      size_t i;
     321      strcpy (n, match_lines ? line_beg : word_beg);
     322      i = strlen(n);
     323      memcpy (n + i, pattern, size);
     324      i += size;
     325      strcpy (n + i, match_lines ? line_end : word_end);
     326      i += strlen (n + i);
     327      pattern = n;
     328      size = i;
     329    }
     330
     331  dfacomp (pattern, size, &dfa, 1);
     332  kwsmusts ();
     333}
     334
     335static size_t
     336EGexecute (char const *buf, size_t size, size_t *match_size, int exact)
     337{
     338  register char const *buflim, *beg, *end;
     339  char eol = eolbyte;
     340  int backref, start, len;
     341  struct kwsmatch kwsm;
     342  size_t i;
     343#ifdef MBS_SUPPORT
     344  char *mb_properties = NULL;
     345#endif /* MBS_SUPPORT */
     346
     347#ifdef MBS_SUPPORT
     348  if (MB_CUR_MAX > 1 && kwset)
     349    mb_properties = check_multibyte_string(buf, size);
     350#endif /* MBS_SUPPORT */
     351
     352  buflim = buf + size;
     353
     354  for (beg = end = buf; end < buflim; beg = end)
     355    {
     356      if (!exact)
     357        {
     358          if (kwset)
     359            {
     360              /* Find a possible match using the KWset matcher. */
     361              size_t offset = kwsexec (kwset, beg, buflim - beg, &kwsm);
     362              if (offset == (size_t) -1)
     363                goto failure;
     364              beg += offset;
     365              /* Narrow down to the line containing the candidate, and
     366                 run it through DFA. */
     367              end = memchr(beg, eol, buflim - beg);
     368              end++;
     369#ifdef MBS_SUPPORT
     370              if (MB_CUR_MAX > 1 && mb_properties[beg - buf] == 0)
     371                continue;
     372#endif
     373              while (beg > buf && beg[-1] != eol)
     374                --beg;
     375              if (kwsm.index < kwset_exact_matches)
     376                goto success_in_beg_and_end;
     377              if (dfaexec (&dfa, beg, end - beg, &backref) == (size_t) -1)
     378                continue;
     379            }
     380          else
     381            {
     382              /* No good fixed strings; start with DFA. */
     383              size_t offset = dfaexec (&dfa, beg, buflim - beg, &backref);
     384              if (offset == (size_t) -1)
     385                break;
     386              /* Narrow down to the line we've found. */
     387              beg += offset;
     388              end = memchr (beg, eol, buflim - beg);
     389              end++;
     390              while (beg > buf && beg[-1] != eol)
     391                --beg;
     392            }
     393          /* Successful, no backreferences encountered! */
     394          if (!backref)
     395            goto success_in_beg_and_end;
     396        }
     397      else
     398        end = beg + size;
     399
     400      /* If we've made it to this point, this means DFA has seen
     401         a probable match, and we need to run it through Regex. */
     402      for (i = 0; i < pcount; i++)
     403        {
     404          patterns[i].regexbuf.not_eol = 0;
     405          if (0 <= (start = re_search (&(patterns[i].regexbuf), beg,
     406                                       end - beg - 1, 0,
     407                                       end - beg - 1, &(patterns[i].regs))))
     408            {
     409              len = patterns[i].regs.end[0] - start;
     410              if (exact && !match_words)
     411                goto success_in_start_and_len;
     412              if ((!match_lines && !match_words)
     413                  || (match_lines && len == end - beg - 1))
     414                goto success_in_beg_and_end;
     415              /* If -w, check if the match aligns with word boundaries.
     416                 We do this iteratively because:
     417                 (a) the line may contain more than one occurence of the
     418                 pattern, and
     419                 (b) Several alternatives in the pattern might be valid at a
     420                 given point, and we may need to consider a shorter one to
     421                 find a word boundary.  */
     422              if (match_words)
     423                while (start >= 0)
     424                  {
     425                    if ((start == 0 || !WCHAR ((unsigned char) beg[start - 1]))
     426                        && (len == end - beg - 1
     427                            || !WCHAR ((unsigned char) beg[start + len])))
     428                      goto success_in_beg_and_end;
     429                    if (len > 0)
     430                      {
     431                        /* Try a shorter length anchored at the same place. */
     432                        --len;
     433                        patterns[i].regexbuf.not_eol = 1;
     434                        len = re_match (&(patterns[i].regexbuf), beg,
     435                                        start + len, start,
     436                                        &(patterns[i].regs));
     437                      }
     438                    if (len <= 0)
     439                      {
     440                        /* Try looking further on. */
     441                        if (start == end - beg - 1)
     442                          break;
     443                        ++start;
     444                        patterns[i].regexbuf.not_eol = 0;
     445                        start = re_search (&(patterns[i].regexbuf), beg,
     446                                           end - beg - 1,
     447                                           start, end - beg - 1 - start,
     448                                           &(patterns[i].regs));
     449                        len = patterns[i].regs.end[0] - start;
     450                      }
     451                  }
     452            }
     453        } /* for Regex patterns.  */
     454    } /* for (beg = end ..) */
     455
     456 failure:
     457#ifdef MBS_SUPPORT
     458  if (MB_CUR_MAX > 1 && mb_properties)
     459    free (mb_properties);
     460#endif /* MBS_SUPPORT */
     461  return (size_t) -1;
     462
     463 success_in_beg_and_end:
     464  len = end - beg;
     465  start = beg - buf;
     466  /* FALLTHROUGH */
     467
     468 success_in_start_and_len:
     469#ifdef MBS_SUPPORT
     470  if (MB_CUR_MAX > 1 && mb_properties)
     471    free (mb_properties);
     472#endif /* MBS_SUPPORT */
     473  *match_size = len;
     474  return start;
     475}
     476
     477static void
     478Fcompile (char const *pattern, size_t size)
     479{
     480  char const *beg, *lim, *err;
     481
     482  kwsinit ();
     483  beg = pattern;
     484  do
     485    {
     486      for (lim = beg; lim < pattern + size && *lim != '\n'; ++lim)
     487        ;
     488      if ((err = kwsincr (kwset, beg, lim - beg)) != 0)
     489        error (2, 0, err);
     490      if (lim < pattern + size)
     491        ++lim;
     492      beg = lim;
     493    }
     494  while (beg < pattern + size);
     495
     496  if ((err = kwsprep (kwset)) != 0)
     497    error (2, 0, err);
     498}
     499
     500static size_t
     501Fexecute (char const *buf, size_t size, size_t *match_size, int exact)
     502{
     503  register char const *beg, *try, *end;
     504  register size_t len;
     505  char eol = eolbyte;
     506  struct kwsmatch kwsmatch;
     507#ifdef MBS_SUPPORT
     508  char *mb_properties;
     509  if (MB_CUR_MAX > 1)
     510    mb_properties = check_multibyte_string (buf, size);
     511#endif /* MBS_SUPPORT */
     512
     513  for (beg = buf; beg <= buf + size; ++beg)
     514    {
     515      size_t offset = kwsexec (kwset, beg, buf + size - beg, &kwsmatch);
     516      if (offset == (size_t) -1)
     517        goto failure;
     518#ifdef MBS_SUPPORT
     519      if (MB_CUR_MAX > 1 && mb_properties[offset+beg-buf] == 0)
     520        continue; /* It is a part of multibyte character.  */
     521#endif /* MBS_SUPPORT */
     522      beg += offset;
     523      len = kwsmatch.size[0];
     524      if (exact && !match_words)
     525        goto success_in_beg_and_len;
     526      if (match_lines)
     527        {
     528          if (beg > buf && beg[-1] != eol)
     529            continue;
     530          if (beg + len < buf + size && beg[len] != eol)
     531            continue;
     532          goto success;
     533        }
     534      else if (match_words)
     535        for (try = beg; len; )
     536          {
     537            if (try > buf && WCHAR((unsigned char) try[-1]))
     538              break;
     539            if (try + len < buf + size && WCHAR((unsigned char) try[len]))
     540              {
     541                offset = kwsexec (kwset, beg, --len, &kwsmatch);
     542                if (offset == (size_t) -1)
     543                  {
     544#ifdef MBS_SUPPORT
     545                    if (MB_CUR_MAX > 1)
     546                      free (mb_properties);
     547#endif /* MBS_SUPPORT */
     548                    return offset;
     549                  }
     550                try = beg + offset;
     551                len = kwsmatch.size[0];
     552              }
     553            else
     554              goto success;
     555          }
     556      else
     557        goto success;
     558    }
     559
     560 failure:
     561#ifdef MBS_SUPPORT
     562  if (MB_CUR_MAX > 1)
     563    free (mb_properties);
     564#endif /* MBS_SUPPORT */
     565  return -1;
     566
     567 success:
     568  end = memchr (beg + len, eol, (buf + size) - (beg + len));
     569  end++;
     570  while (buf < beg && beg[-1] != eol)
     571    --beg;
     572  len = end - beg;
     573  /* FALLTHROUGH */
     574
     575 success_in_beg_and_len:
     576  *match_size = len;
     577#ifdef MBS_SUPPORT
     578  if (MB_CUR_MAX > 1)
     579    free (mb_properties);
     580#endif /* MBS_SUPPORT */
     581  return beg - buf;
     582}
     583
     584#if HAVE_LIBPCRE
     585/* Compiled internal form of a Perl regular expression.  */
     586static pcre *cre;
     587
     588/* Additional information about the pattern.  */
     589static pcre_extra *extra;
     590#endif
     591
     592static void
     593Pcompile (char const *pattern, size_t size)
     594{
     595#if !HAVE_LIBPCRE
     596  error (2, 0, _("The -P option is not supported"));
     597#else
     598  int e;
     599  char const *ep;
     600  char *re = xmalloc (4 * size + 7);
     601  int flags = PCRE_MULTILINE | (match_icase ? PCRE_CASELESS : 0);
     602  char const *patlim = pattern + size;
     603  char *n = re;
     604  char const *p;
     605  char const *pnul;
     606
     607  /* FIXME: Remove this restriction.  */
     608  if (eolbyte != '\n')
     609    error (2, 0, _("The -P and -z options cannot be combined"));
     610
     611  *n = '\0';
     612  if (match_lines)
     613    strcpy (n, "^(");
     614  if (match_words)
     615    strcpy (n, "\\b(");
     616  n += strlen (n);
     617
     618  /* The PCRE interface doesn't allow NUL bytes in the pattern, so
     619     replace each NUL byte in the pattern with the four characters
     620     "\000", removing a preceding backslash if there are an odd
     621     number of backslashes before the NUL.
     622
     623     FIXME: This method does not work with some multibyte character
     624     encodings, notably Shift-JIS, where a multibyte character can end
     625     in a backslash byte.  */
     626  for (p = pattern; (pnul = memchr (p, '\0', patlim - p)); p = pnul + 1)
     627    {
     628      memcpy (n, p, pnul - p);
     629      n += pnul - p;
     630      for (p = pnul; pattern < p && p[-1] == '\\'; p--)
     631        continue;
     632      n -= (pnul - p) & 1;
     633      strcpy (n, "\\000");
     634      n += 4;
     635    }
     636
     637  memcpy (n, p, patlim - p);
     638  n += patlim - p;
     639  *n = '\0';
     640  if (match_words)
     641    strcpy (n, ")\\b");
     642  if (match_lines)
     643    strcpy (n, ")$");
     644
     645  cre = pcre_compile (re, flags, &ep, &e, pcre_maketables ());
     646  if (!cre)
     647    error (2, 0, ep);
     648
     649  extra = pcre_study (cre, 0, &ep);
     650  if (ep)
     651    error (2, 0, ep);
     652
     653  free (re);
     654#endif
     655}
     656
     657static size_t
     658Pexecute (char const *buf, size_t size, size_t *match_size, int exact)
     659{
     660#if !HAVE_LIBPCRE
     661  abort ();
     662  return -1;
     663#else
     664  /* This array must have at least two elements; everything after that
     665     is just for performance improvement in pcre_exec.  */
     666  int sub[300];
     667
     668  int e = pcre_exec (cre, extra, buf, size, 0, 0,
     669                     sub, sizeof sub / sizeof *sub);
     670
     671  if (e <= 0)
     672    {
     673      switch (e)
     674        {
     675        case PCRE_ERROR_NOMATCH:
     676          return -1;
     677
     678        case PCRE_ERROR_NOMEMORY:
     679          error (2, 0, _("Memory exhausted"));
     680
     681        default:
     682          abort ();
     683        }
     684    }
     685  else
     686    {
     687      /* Narrow down to the line we've found.  */
     688      char const *beg = buf + sub[0];
     689      char const *end = buf + sub[1];
     690      char const *buflim = buf + size;
     691      char eol = eolbyte;
     692      if (!exact)
     693        {
     694          end = memchr (end, eol, buflim - end);
     695          end++;
     696          while (buf < beg && beg[-1] != eol)
     697            --beg;
     698        }
     699
     700      *match_size = end - beg;
     701      return beg - buf;
     702    }
     703#endif
     704}
     705
     706struct matcher const matchers[] = {
     707  { "default", Gcompile, EGexecute },
     708  { "grep", Gcompile, EGexecute },
     709  { "egrep", Ecompile, EGexecute },
     710  { "awk", Ecompile, EGexecute },
     711  { "fgrep", Fcompile, Fexecute },
     712  { "perl", Pcompile, Pexecute },
     713  { "", 0, 0 },
     714};
  • tests/fmbtest.sh

    diff -urN grep-2.5.1a.orig/tests/fmbtest.sh grep-2.5.1a/tests/fmbtest.sh
    old new  
     1#!/bin/sh
     2
     3: ${srcdir=.}
     4
     5# If cs_CZ.UTF-8 locale doesn't work, skip this test silently
     6LC_ALL=cs_CZ.UTF-8 locale -k LC_CTYPE 2>/dev/null | ${GREP} -q charmap.*UTF-8 \
     7  || exit 77
     8
     9failures=0
     10
     11cat > csinput <<EOF
     1201 ÅœluÅ¥oučká číše
     13ČíŠE 02
     1403 Z číší Čiší cosi
     1504 Čí
     16Å e 05
     1706 ČČČČČČČíšČÍŠčíš
     1807 ČČČ ČČČČíšČÍŠčíšEEEE
     19čAs 08
     2009Čapka
     2110ČaSy se měnÍ
     22ČÍšE11
     23Čas12
     24𝇕ČÍšE𝇓13
     25ŜČÍšE𝇓14
     26𝇕ČÍšEÅœ15
     27ŜČÍšEÅœ16
     28ČÍšE𝇓17
     29ČÍšEÅœ18
     3019𝇕ČÍše
     3120ŜČÍše
     32EOF
     33cat > cspatfile <<EOF
     34ČÍšE
     35Čas
     36EOF
     37
     38for mode in F G E; do
     39
     40test1="$(echo `LC_ALL=cs_CZ.UTF-8 ${GREP} -${mode} -f cspatfile csinput \
     41               | LC_ALL=C sed 's/^.*\([0-9][0-9]\).*$/\1/'`)"
     42if test "$test1" != "11 12 13 14 15 16 17 18"; then
     43  echo "Test #1 ${mode} failed: $test1"
     44  failures=1
     45fi
     46
     47test2="$(echo `LC_ALL=cs_CZ.UTF-8 ${GREP} -${mode}i -f cspatfile csinput \
     48               | LC_ALL=C sed 's/^.*\([0-9][0-9]\).*$/\1/'`)"
     49if test "$test2" != "01 02 07 08 10 11 12 13 14 15 16 17 18 19 20"; then
     50  echo "Test #2 ${mode} failed: $test2"
     51  failures=1
     52fi
     53
     54test3="$(echo `LC_ALL=cs_CZ.UTF-8 ${GREP} -${mode}i -e 'ČÍšE' -e 'Čas' csinput \
     55               | LC_ALL=C sed 's/^.*\([0-9][0-9]\).*$/\1/'`)"
     56if test "$test3" != "01 02 07 08 10 11 12 13 14 15 16 17 18 19 20"; then
     57  echo "Test #3 ${mode} failed: $test3"
     58  failures=1
     59fi
     60
     61test4="$(echo `LC_ALL=cs_CZ.UTF-8 ${GREP} -${mode}iw -f cspatfile csinput \
     62               | LC_ALL=C sed 's/^.*\([0-9][0-9]\).*$/\1/'`)"
     63if test "$test4" != "01 02 08 13 17 19"; then
     64  echo "Test #4 ${mode} failed: $test4"
     65  failures=1
     66fi
     67
     68done
     69
     70# Test that -F --color=always prefers longer matches.
     71test5="`echo 'Cosi tu ČišÍ...' \
     72        | LC_ALL=cs_CZ.UTF-8 ${GREP} --color=always -Fi -e 'čiÅ¡' -e 'čiší'`"
     73if echo "$test5" | LC_ALL=C ${GREP} -q 'Cosi tu .*\[.*mČišÍ.*\[.*m\(.\[K\)\?\.\.\.'; then
     74  :
     75else
     76  echo "Test #5 F failed: $test5"
     77  failures=1
     78fi
     79
     80for mode in G E; do
     81
     82# Test that -{G,E} --color=always prefers earlier pattern matches.
     83test6="`echo 'Cosi tu ČišÍ...' \
     84        | LC_ALL=cs_CZ.UTF-8 ${GREP} --color=always -${mode}i -e 'čiÅ¡' -e 'čiší'`"
     85if echo "$test6" | LC_ALL=C ${GREP} -q 'Cosi tu .*\[.*mČiÅ¡.*\[.*m\(.\[K\)\?Í\.\.\.'; then
     86  :
     87else
     88  echo "Test #6 ${mode} failed: $test6"
     89  failures=1
     90fi
     91
     92# Test that -{G,E} --color=always prefers earlier pattern matches.
     93test7="`echo 'Cosi tu ČišÍ...' \
     94        | LC_ALL=cs_CZ.UTF-8 ${GREP} --color=always -${mode}i -e 'čiší' -e 'čiÅ¡'`"
     95if echo "$test7" | LC_ALL=C ${GREP} -q 'Cosi tu .*\[.*mČišÍ.*\[.*m\(.\[K\)\?\.\.\.'; then
     96  :
     97else
     98  echo "Test #7 ${mode} failed: $test7"
     99  failures=1
     100fi
     101
     102test8="$(echo `LC_ALL=cs_CZ.UTF-8 ${GREP} -${mode}i -e 'Č.Å¡E' -e 'Č[a-f]s' csinput \
     103               | LC_ALL=C sed 's/^.*\([0-9][0-9]\).*$/\1/'`)"
     104if test "$test8" != "01 02 07 08 10 11 12 13 14 15 16 17 18 19 20"; then
     105  echo "Test #8 ${mode} failed: $test8"
     106  failures=1
     107fi
     108
     109done
     110
     111exit $failures
  • tests/Makefile.am

    diff -urN grep-2.5.1a.orig/tests/Makefile.am grep-2.5.1a/tests/Makefile.am
    old new  
    33AWK=@AWK@
    44
    55TESTS = warning.sh khadafy.sh spencer1.sh bre.sh ere.sh \
    6         status.sh empty.sh options.sh backref.sh file.sh
     6        status.sh empty.sh options.sh backref.sh file.sh \
     7        fmbtest.sh
    78EXTRA_DIST = $(TESTS) \
    89             khadafy.lines khadafy.regexp \
    910             spencer1.awk spencer1.tests \
  • tests/Makefile.in

    diff -urN grep-2.5.1a.orig/tests/Makefile.in grep-2.5.1a/tests/Makefile.in
    old new  
    9797AWK = @AWK@
    9898
    9999TESTS = warning.sh khadafy.sh spencer1.sh bre.sh ere.sh \
    100         status.sh empty.sh options.sh backref.sh file.sh
     100        status.sh empty.sh options.sh backref.sh file.sh \
     101        fmbtest.sh
    101102
    102103EXTRA_DIST = $(TESTS) \
    103104             khadafy.lines khadafy.regexp \
Note: See TracBrowser for help on using the repository browser.