source: patches/grep-2.5.3-i18n-1.patch@ 0f6ac75

clfs-1.2 clfs-2.1 clfs-3.0.0-systemd clfs-3.0.0-sysvinit systemd sysvinit
Last change on this file since 0f6ac75 was 318408a, checked in by Jim Gifford <clfs@…>, 16 years ago

Added Internationalization Patch to Grep

  • Property mode set to 100644
File size: 26.9 KB
  • lib/posix/regex.h

    Submitted By: Ken Moffat <ken at linuxfromscratch dot org>
    Date: 2008-02-19
    Initial Package Version: 2.5.3
    Upstream Status: uncertain
    Origin: from debian.
    Description: Various fixes, particularly speed improvements for UTF-8 locales.
    Also adds a 'standard input' marker into the results for certain obscure uses.
    
    diff -Naur grep-2.5.3.orig/lib/posix/regex.h grep-2.5.3.lfs/lib/posix/regex.h
    old new  
    165165   treated as 'a\{1'.  */
    166166#define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1)
    167167
     168/* If this bit is set, then ignore case when matching.
     169   If not set, then case is significant.  */
     170#define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1)
     171
    168172/* This global variable defines the particular regexp syntax to use (for
    169173   some interfaces).  When a regexp is compiled, the syntax used is
    170174   stored in the pattern buffer, so changing this does not affect
  • grep-2.5.3.

    diff -Naur grep-2.5.3.orig/src/dfa.c grep-2.5.3.lfs/src/dfa.c
    old new  
    594594                /* build character class.  */
    595595                {
    596596                  wctype_t wt;
     597                  /* NOTE:
     598                   * when case_fold, character class [:upper:] and [:lower:]
     599                   * should be treated as [:alpha:], this is the same way
     600                   * of glibc/posix/regcomp.c:build_charclass().
     601                   * reported by Bug#276202
     602                   * - fixed by Fumitoshi UKAI
     603                   */
     604                  if (case_fold
     605                      && (strcmp (str, "upper") == 0 || strcmp (str, "lower") == 0))
     606                      strcpy (str, "alpha");
     607
    597608                  /* Query the character class as wctype_t.  */
    598609                  wt = wctype (str);
    599610
     
    681692          REALLOC_IF_NECESSARY(work_mbc->range_ends, wchar_t,
    682693                               range_ends_al, work_mbc->nranges + 1);
    683694          work_mbc->range_ends[work_mbc->nranges++] = (wchar_t)wc2;
     695          if (case_fold
     696              && (iswlower((wint_t)wc) || iswupper((wint_t)wc))
     697              && (iswlower((wint_t)wc2) || iswupper((wint_t)wc2))) {
     698            wint_t altcase;
     699            altcase = wc;
     700            if (iswlower((wint_t)wc))
     701              altcase = towupper((wint_t)wc);
     702            else
     703              altcase = towlower((wint_t)wc);
     704            REALLOC_IF_NECESSARY(work_mbc->range_sts, wchar_t,
     705                                 range_sts_al, work_mbc->nranges + 1);
     706            work_mbc->range_sts[work_mbc->nranges] = (wchar_t)altcase;
     707           
     708            altcase = wc2;
     709            if (iswlower((wint_t)wc2))
     710              altcase = towupper((wint_t)wc2);
     711            else
     712              altcase = towlower((wint_t)wc2);
     713            REALLOC_IF_NECESSARY(work_mbc->range_ends, wchar_t,
     714                                 range_ends_al, work_mbc->nranges + 1);
     715            work_mbc->range_ends[work_mbc->nranges++] = (wchar_t)altcase;
     716           
     717          }
    684718        }
    685719      else if (wc != WEOF)
    686720        /* build normal characters.  */
     
    688722          REALLOC_IF_NECESSARY(work_mbc->chars, wchar_t, chars_al,
    689723                               work_mbc->nchars + 1);
    690724          work_mbc->chars[work_mbc->nchars++] = (wchar_t)wc;
     725          if (case_fold && (iswlower((wint_t) wc) || iswupper((wint_t) wc)))
     726            {
     727                wint_t altcase;
     728
     729                altcase = wc;           /* keeps compiler happy */
     730                if (iswlower((wint_t) wc))
     731                  altcase = towupper((wint_t) wc);
     732                else if (iswupper((wint_t) wc))
     733                  altcase = towlower((wint_t) wc);
     734
     735                REALLOC_IF_NECESSARY(work_mbc->chars, wchar_t, chars_al,
     736                               work_mbc->nchars + 1);
     737                work_mbc->chars[work_mbc->nchars++] = (wchar_t) altcase;
     738            }
    691739        }
    692740    }
    693741  while ((wc = wc1) != L']');
  • src/grep.c

    diff -Naur grep-2.5.3.orig/src/grep.c grep-2.5.3.lfs/src/grep.c
    old new  
    274274#endif
    275275;
    276276
     277/* Default for `file_list' if no files are given on the command line. */
     278static char *stdin_argv[] =
     279{
     280  "-", NULL
     281};
     282
    277283/* Non-boolean long options that have no corresponding short equivalents.  */
    278284enum
    279285{
     
    534540         for byte sentinels fore and aft.  */
    535541      newalloc = newsize + pagesize + 1;
    536542
    537       newbuf = bufalloc < newalloc ? xmalloc (bufalloc = newalloc) : buffer;
     543      newbuf = bufalloc < newalloc ? malloc (bufalloc = newalloc) : buffer;
     544      if (newbuf == NULL)
     545        {
     546          int saved_errno = errno;
     547          free (buffer);
     548          bufalloc = ALIGN_TO (INITIAL_BUFSIZE, pagesize) + pagesize + 1;
     549          buffer = xmalloc (bufalloc);
     550          errno = saved_errno;
     551          return 0;
     552        }
    538553      readbuf = ALIGN_TO (newbuf + 1 + save, pagesize);
    539554      bufbeg = readbuf - save;
    540555      memmove (bufbeg, buffer + saved_offset, save);
     
    18251840  FILE *fp;
    18261841  extern char *optarg;
    18271842  extern int optind;
     1843  char **file_list;
    18281844
    18291845  initialize_main (&argc, &argv);
    18301846  program_name = argv[0];
     
    22442260  if (max_count == 0)
    22452261    exit (1);
    22462262
    2247   if (optind < argc)
     2263  file_list = (optind == argc ? stdin_argv : &argv[optind]);
     2264
     2265  status = 1;
     2266  while (1)
    22482267    {
    2249         status = 1;
    2250         do
     2268      char *file = *file_list++;
     2269
     2270      if (file == NULL)
     2271        break;
     2272
     2273      if ((included_patterns || excluded_patterns)
     2274          && !isdir (file))
    22512275        {
    2252           char *file = argv[optind];
    2253           if ((included_patterns || excluded_patterns)
    2254               && !isdir (file))
    2255             {
    2256               if (included_patterns &&
    2257                   ! excluded_filename (included_patterns, file, 0))
    2258                 continue;
    2259               if (excluded_patterns &&
    2260                   excluded_filename (excluded_patterns, file, 0))
    2261                 continue;
    2262             }
    2263           status &= grepfile (strcmp (file, "-") == 0 ? (char *) NULL : file,
    2264                               &stats_base);
     2276          if (included_patterns &&
     2277              ! excluded_filename (included_patterns, file, 0))
     2278            continue;
     2279          if (excluded_patterns &&
     2280              excluded_filename (excluded_patterns, file, 0))
     2281            continue;
    22652282        }
    2266         while ( ++optind < argc);
     2283      status &= grepfile (strcmp (file, "-") == 0
     2284                          ? (char *) NULL : file, &stats_base);
    22672285    }
    2268   else
    2269     status = grepfile ((char *) NULL, &stats_base);
    22702286
    22712287  /* We register via atexit() to test stdout.  */
    22722288  exit (errseen ? 2 : status);
  • src/search.c

    diff -Naur grep-2.5.3.orig/src/search.c grep-2.5.3.lfs/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
    2427
     28#include <assert.h>
     29
    2530#include <sys/types.h>
    2631
    2732#include "mbsupport.h"
     
    4348#ifdef HAVE_LIBPCRE
    4449# include <pcre.h>
    4550#endif
     51#ifdef HAVE_LANGINFO_CODESET
     52# include <langinfo.h>
     53#endif
    4654
    4755#define NCHAR (UCHAR_MAX + 1)
    4856
     
    6876    error (2, 0, _("memory exhausted"));
    6977}
    7078
     79/* UTF-8 encoding allows some optimizations that we can't otherwise
     80   assume in a multibyte encoding. */
     81static int using_utf8;
     82
     83void
     84check_utf8 (void)
     85{
     86#ifdef HAVE_LANGINFO_CODESET
     87  if (strcmp (nl_langinfo (CODESET), "UTF-8") == 0)
     88    using_utf8 = 1;
     89#endif
     90}
     91
    7192#ifndef FGREP_PROGRAM
    7293/* DFA compiled regexp. */
    7394static struct dfa dfa;
     
    134155}
    135156#endif /* !FGREP_PROGRAM */
    136157
    137 #ifdef MBS_SUPPORT
    138 /* This function allocate the array which correspond to "buf".
    139    Then this check multibyte string and mark on the positions which
    140    are not single byte character nor the first byte of a multibyte
    141    character.  Caller must free the array.  */
    142 static char*
    143 check_multibyte_string(char const *buf, size_t size)
    144 {
    145   char *mb_properties = xmalloc(size);
    146   mbstate_t cur_state;
    147   wchar_t wc;
    148   int i;
    149 
    150   memset(&cur_state, 0, sizeof(mbstate_t));
    151   memset(mb_properties, 0, sizeof(char)*size);
    152 
    153   for (i = 0; i < size ;)
    154     {
    155       size_t mbclen;
    156       mbclen = mbrtowc(&wc, buf + i, size - i, &cur_state);
    157 
    158       if (mbclen == (size_t) -1 || mbclen == (size_t) -2 || mbclen == 0)
    159         {
    160           /* An invalid sequence, or a truncated multibyte character.
    161              We treat it as a single byte character.  */
    162           mbclen = 1;
    163         }
    164       else if (match_icase)
    165         {
    166           if (iswupper((wint_t)wc))
    167             {
    168               wc = towlower((wint_t)wc);
    169               wcrtomb(buf + i, wc, &cur_state);
    170             }
    171         }
    172       mb_properties[i] = mbclen;
    173       i += mbclen;
    174     }
    175 
    176   return mb_properties;
    177 }
    178 #endif /* MBS_SUPPORT */
    179 
    180158#if defined(GREP_PROGRAM) || defined(EGREP_PROGRAM)
    181159#ifdef EGREP_PROGRAM
    182160COMPILE_FCT(Ecompile)
     
    193171  size_t total = size;
    194172  char const *motif = pattern;
    195173
    196 #if 0
     174  check_utf8 ();
    197175  if (match_icase)
    198176    syntax_bits |= RE_ICASE;
    199 #endif
    200177  re_set_syntax (syntax_bits);
    201178  dfasyntax (syntax_bits, match_icase, eolbyte);
    202179
     
    301278  char eol = eolbyte;
    302279  int backref, start, len, best_len;
    303280  struct kwsmatch kwsm;
     281  static int use_dfa;
     282  static int use_dfa_checked = 0;
    304283  size_t i, ret_val;
    305284#ifdef MBS_SUPPORT
    306   char *mb_properties = NULL;
    307   if (MB_CUR_MAX > 1)
     285  const char *last_char = NULL;
     286  int mb_cur_max = MB_CUR_MAX;
     287  mbstate_t mbs;
     288  memset (&mbs, '\0', sizeof (mbstate_t));
     289#endif /* MBS_SUPPORT */
     290
     291  if (!use_dfa_checked)
    308292    {
    309       if (match_icase)
    310         {
    311           char *case_buf = xmalloc(size);
    312           memcpy(case_buf, buf, size);
    313           if (start_ptr)
    314             start_ptr = case_buf + (start_ptr - buf);
    315           buf = case_buf;
    316         }
    317       if (kwset)
    318         mb_properties = check_multibyte_string(buf, size);
    319     }
     293      char *grep_use_dfa = getenv ("GREP_USE_DFA");
     294      if (!grep_use_dfa)
     295        {
     296#ifdef MBS_SUPPORT
     297          /* Turn off DFA when processing multibyte input. */
     298          use_dfa = (MB_CUR_MAX == 1);
     299#else
     300          use_dfa = 1;
    320301#endif /* MBS_SUPPORT */
     302        }
     303      else
     304        {
     305          use_dfa = atoi (grep_use_dfa);
     306        }
     307
     308      use_dfa_checked = 1;
     309    }
    321310
    322311  buflim = buf + size;
    323312
     
    329318          if (kwset)
    330319            {
    331320              /* Find a possible match using the KWset matcher. */
    332               size_t offset = kwsexec (kwset, beg, buflim - beg, &kwsm);
     321#ifdef MBS_SUPPORT
     322              size_t bytes_left = 0;
     323#endif /* MBS_SUPPORT */
     324              size_t offset;
     325#ifdef MBS_SUPPORT
     326              /* kwsexec doesn't work with match_icase and multibyte input. */
     327              if (match_icase && mb_cur_max > 1)
     328                /* Avoid kwset */
     329                offset = 0;
     330              else
     331#endif /* MBS_SUPPORT */
     332              offset = kwsexec (kwset, beg, buflim - beg, &kwsm);
    333333              if (offset == (size_t) -1)
    334                 goto failure;
     334                return (size_t)-1;
     335#ifdef MBS_SUPPORT
     336              if (mb_cur_max > 1 && !using_utf8)
     337                {
     338                  bytes_left = offset;
     339                  while (bytes_left)
     340                    {
     341                      size_t mlen = mbrlen (beg, bytes_left, &mbs);
     342
     343                      last_char = beg;
     344                      if (mlen == (size_t) -1 || mlen == 0)
     345                        {
     346                          /* Incomplete character: treat as single-byte. */
     347                          memset (&mbs, '\0', sizeof (mbstate_t));
     348                          beg++;
     349                          bytes_left--;
     350                          continue;
     351                        }
     352
     353                      if (mlen == (size_t) -2)
     354                        /* Offset points inside multibyte character:
     355                         * no good. */
     356                        break;
     357
     358                      beg += mlen;
     359                      bytes_left -= mlen;
     360                    }
     361                }
     362              else
     363#endif /* MBS_SUPPORT */
    335364              beg += offset;
    336365              /* Narrow down to the line containing the candidate, and
    337366                 run it through DFA. */
    338367              end = memchr(beg, eol, buflim - beg);
    339368              end++;
    340369#ifdef MBS_SUPPORT
    341               if (MB_CUR_MAX > 1 && mb_properties[beg - buf] == 0)
     370              if (mb_cur_max > 1 && bytes_left)
    342371                continue;
    343372#endif
    344373              while (beg > buf && beg[-1] != eol)
    345374                --beg;
    346               if (kwsm.index < kwset_exact_matches)
     375              if (
     376#ifdef MBS_SUPPORT
     377                  !(match_icase && mb_cur_max > 1) &&
     378#endif /* MBS_SUPPORT */
     379                  (kwsm.index < kwset_exact_matches))
    347380                goto success;
    348               if (dfaexec (&dfa, beg, end - beg, &backref) == (size_t) -1)
     381              if (use_dfa &&
     382                  dfaexec (&dfa, beg, end - beg, &backref) == (size_t) -1)
    349383                continue;
    350384            }
    351385          else
    352386            {
    353387              /* No good fixed strings; start with DFA. */
    354               size_t offset = dfaexec (&dfa, beg, buflim - beg, &backref);
     388#ifdef MBS_SUPPORT
     389              size_t bytes_left = 0;
     390#endif /* MBS_SUPPORT */
     391              size_t offset = 0;
     392              if (use_dfa)
     393                offset = dfaexec (&dfa, beg, buflim - beg, &backref);
    355394              if (offset == (size_t) -1)
    356395                break;
    357396              /* Narrow down to the line we've found. */
     397#ifdef MBS_SUPPORT
     398              if (mb_cur_max > 1 && !using_utf8)
     399                {
     400                  bytes_left = offset;
     401                  while (bytes_left)
     402                    {
     403                      size_t mlen = mbrlen (beg, bytes_left, &mbs);
     404
     405                      last_char = beg;
     406                      if (mlen == (size_t) -1 || mlen == 0)
     407                        {
     408                          /* Incomplete character: treat as single-byte. */
     409                          memset (&mbs, '\0', sizeof (mbstate_t));
     410                          beg++;
     411                          bytes_left--;
     412                          continue;
     413                        }
     414
     415                      if (mlen == (size_t) -2)
     416                        /* Offset points inside multibyte character:
     417                         * no good. */
     418                        break;
     419
     420                      beg += mlen;
     421                      bytes_left -= mlen;
     422                    }
     423                }
     424              else
     425#endif /* MBS_SUPPORT */
    358426              beg += offset;
    359427              end = memchr (beg, eol, buflim - beg);
    360428              end++;
     429#ifdef MBS_SUPPORT
     430              if (mb_cur_max > 1 && bytes_left)
     431                continue;
     432#endif /* MBS_SUPPORT */
    361433              while (beg > buf && beg[-1] != eol)
    362434                --beg;
    363435            }
    364436          /* Successful, no backreferences encountered! */
    365           if (!backref)
     437          if (use_dfa && !backref)
    366438            goto success;
    367439        }
    368440      else
     
    408480              if (match_words)
    409481                while (match <= best_match)
    410482                  {
    411                     if ((match == buf || !WCHAR ((unsigned char) match[-1]))
    412                         && (len == end - beg - 1
    413                             || !WCHAR ((unsigned char) match[len])))
    414                       goto assess_pattern_match;
     483                    int lword_match = 0;
     484                    if (match == buf)
     485                      lword_match = 1;
     486                    else
     487                      {
     488                        assert (start > 0);
     489#ifdef MBS_SUPPORT
     490                        if (mb_cur_max > 1)
     491                          {
     492                            const char *s;
     493                            int mr;
     494                            wchar_t pwc;
     495                            if (using_utf8)
     496                              {
     497                                s = match - 1;
     498                                while (s > buf
     499                                       && (unsigned char) *s >= 0x80
     500                                       && (unsigned char) *s <= 0xbf)
     501                                  --s;
     502                              }
     503                            else
     504                              s = last_char;
     505                            mr = mbtowc (&pwc, s, match - s);
     506                            if (mr <= 0)
     507                              {
     508                                memset (&mbs, '\0', sizeof (mbstate_t));
     509                                lword_match = 1;
     510                              }
     511                            else if (!(iswalnum (pwc) || pwc == L'_')
     512                                     && mr == (int) (match - s))
     513                              lword_match = 1;
     514                          }
     515                        else
     516#endif /* MBS_SUPPORT */
     517                        if (!WCHAR ((unsigned char) match[-1]))
     518                          lword_match = 1;
     519                      }
     520
     521                    if (lword_match)
     522                      {
     523                        int rword_match = 0;
     524                        if (start + len == end - beg - 1)
     525                          rword_match = 1;
     526                        else
     527                          {
     528#ifdef MBS_SUPPORT
     529                            if (mb_cur_max > 1)
     530                              {
     531                                wchar_t nwc;
     532                                int mr;
     533
     534                                mr = mbtowc (&nwc, buf + start + len,
     535                                             end - buf - start - len - 1);
     536                                if (mr <= 0)
     537                                  {
     538                                    memset (&mbs, '\0', sizeof (mbstate_t));
     539                                    rword_match = 1;
     540                                  }
     541                                else if (!iswalnum (nwc) && nwc != L'_')
     542                                  rword_match = 1;
     543                              }
     544                            else
     545#endif /* MBS_SUPPORT */
     546                            if (!WCHAR ((unsigned char) match[len]))
     547                              rword_match = 1;
     548                          }
     549
     550                        if (rword_match)
     551                          {
     552                            if (!start_ptr)
     553                              /* Returns the whole line. */
     554                              goto success;
     555                            else
     556                              {
     557                                goto assess_pattern_match;
     558                              }
     559                          }
     560                      }
    415561                    if (len > 0)
    416562                      {
    417563                        /* Try a shorter length anchored at the same place. */
     
    475621  *match_size = len;
    476622  ret_val = beg - buf;
    477623 out:
    478 #ifdef MBS_SUPPORT
    479   if (MB_CUR_MAX > 1)
    480     {
    481       if (match_icase)
    482         free((char*)buf);
    483       if (mb_properties)
    484         free(mb_properties);
    485     }
    486 #endif /* MBS_SUPPORT */
    487624  return ret_val;
    488625}
    489626#endif /* defined(GREP_PROGRAM) || defined(EGREP_PROGRAM) */
    490627
     628#ifdef MBS_SUPPORT
     629static int f_i_multibyte; /* whether we're using the new -Fi MB method */
     630static struct
     631{
     632  wchar_t **patterns;
     633  size_t count, maxlen;
     634  unsigned char *match;
     635} Fimb;
     636#endif
     637
    491638#if defined(GREP_PROGRAM) || defined(FGREP_PROGRAM)
    492639COMPILE_FCT(Fcompile)
    493640{
     641  int mb_cur_max = MB_CUR_MAX;
    494642  char const *beg, *lim, *err;
    495643
     644  check_utf8 ();
     645#ifdef MBS_SUPPORT
     646  /* Support -F -i for UTF-8 input. */
     647  if (match_icase && mb_cur_max > 1)
     648    {
     649      mbstate_t mbs;
     650      wchar_t *wcpattern = xmalloc ((size + 1) * sizeof (wchar_t));
     651      const char *patternend = pattern;
     652      size_t wcsize;
     653      kwset_t fimb_kwset = NULL;
     654      char *starts = NULL;
     655      wchar_t *wcbeg, *wclim;
     656      size_t allocated = 0;
     657
     658      memset (&mbs, '\0', sizeof (mbs));
     659# ifdef __GNU_LIBRARY__
     660      wcsize = mbsnrtowcs (wcpattern, &patternend, size, size, &mbs);
     661      if (patternend != pattern + size)
     662        wcsize = (size_t) -1;
     663# else
     664      {
     665        char *patterncopy = xmalloc (size + 1);
     666
     667        memcpy (patterncopy, pattern, size);
     668        patterncopy[size] = '\0';
     669        patternend = patterncopy;
     670        wcsize = mbsrtowcs (wcpattern, &patternend, size, &mbs);
     671        if (patternend != patterncopy + size)
     672          wcsize = (size_t) -1;
     673        free (patterncopy);
     674      }
     675# endif
     676      if (wcsize + 2 <= 2)
     677        {
     678fimb_fail:
     679          free (wcpattern);
     680          free (starts);
     681          if (fimb_kwset)
     682            kwsfree (fimb_kwset);
     683          free (Fimb.patterns);
     684          Fimb.patterns = NULL;
     685        }
     686      else
     687        {
     688          if (!(fimb_kwset = kwsalloc (NULL)))
     689            error (2, 0, _("memory exhausted"));
     690
     691          starts = xmalloc (mb_cur_max * 3);
     692          wcbeg = wcpattern;
     693          do
     694            {
     695              int i;
     696              size_t wclen;
     697
     698              if (Fimb.count >= allocated)
     699                {
     700                  if (allocated == 0)
     701                    allocated = 128;
     702                  else
     703                    allocated *= 2;
     704                  Fimb.patterns = xrealloc (Fimb.patterns,
     705                                            sizeof (wchar_t *) * allocated);
     706                }
     707              Fimb.patterns[Fimb.count++] = wcbeg;
     708              for (wclim = wcbeg;
     709                   wclim < wcpattern + wcsize && *wclim != L'\n'; ++wclim)
     710                *wclim = towlower (*wclim);
     711              *wclim = L'\0';
     712              wclen = wclim - wcbeg;
     713              if (wclen > Fimb.maxlen)
     714                Fimb.maxlen = wclen;
     715              if (wclen > 3)
     716                wclen = 3;
     717              if (wclen == 0)
     718                {
     719                  if ((err = kwsincr (fimb_kwset, "", 0)) != 0)
     720                    error (2, 0, err);
     721                }
     722              else
     723                for (i = 0; i < (1 << wclen); i++)
     724                  {
     725                    char *p = starts;
     726                    int j, k;
     727
     728                    for (j = 0; j < wclen; ++j)
     729                      {
     730                        wchar_t wc = wcbeg[j];
     731                        if (i & (1 << j))
     732                          {
     733                            wc = towupper (wc);
     734                            if (wc == wcbeg[j])
     735                              continue;
     736                          }
     737                        k = wctomb (p, wc);
     738                        if (k <= 0)
     739                          goto fimb_fail;
     740                        p += k;
     741                      }
     742                    if ((err = kwsincr (fimb_kwset, starts, p - starts)) != 0)
     743                      error (2, 0, err);
     744                  }
     745              if (wclim < wcpattern + wcsize)
     746                ++wclim;
     747              wcbeg = wclim;
     748            }
     749          while (wcbeg < wcpattern + wcsize);
     750          f_i_multibyte = 1;
     751          kwset = fimb_kwset;
     752          free (starts);
     753          Fimb.match = xmalloc (Fimb.count);
     754          if ((err = kwsprep (kwset)) != 0)
     755            error (2, 0, err);
     756          return;
     757        }
     758    }
     759#endif /* MBS_SUPPORT */
     760
     761
    496762  kwsinit ();
    497763  beg = pattern;
    498764  do
     
    511777    error (2, 0, err);
    512778}
    513779
     780#ifdef MBS_SUPPORT
     781static int
     782Fimbexec (const char *buf, size_t size, size_t *plen, int exact)
     783{
     784  size_t len, letter, i;
     785  int ret = -1;
     786  mbstate_t mbs;
     787  wchar_t wc;
     788  int patterns_left;
     789
     790  assert (match_icase && f_i_multibyte == 1);
     791  assert (MB_CUR_MAX > 1);
     792
     793  memset (&mbs, '\0', sizeof (mbs));
     794  memset (Fimb.match, '\1', Fimb.count);
     795  letter = len = 0;
     796  patterns_left = 1;
     797  while (patterns_left && len <= size)
     798    {
     799      size_t c;
     800
     801      patterns_left = 0;
     802      if (len < size)
     803        {
     804          c = mbrtowc (&wc, buf + len, size - len, &mbs);
     805          if (c + 2 <= 2)
     806            return ret;
     807
     808          wc = towlower (wc);
     809        }
     810      else
     811        {
     812          c = 1;
     813          wc = L'\0';
     814        }
     815
     816      for (i = 0; i < Fimb.count; i++)
     817        {
     818          if (Fimb.match[i])
     819            {
     820              if (Fimb.patterns[i][letter] == L'\0')
     821                {
     822                  /* Found a match. */
     823                  *plen = len;
     824                  if (!exact && !match_words)
     825                    return 0;
     826                  else
     827                    {
     828                      /* For -w or exact look for longest match.  */
     829                      ret = 0;
     830                      Fimb.match[i] = '\0';
     831                      continue;
     832                    }
     833                }
     834
     835              if (Fimb.patterns[i][letter] == wc)
     836                patterns_left = 1;
     837              else
     838                Fimb.match[i] = '\0';
     839            }
     840        }
     841
     842      len += c;
     843      letter++;
     844    }
     845
     846  return ret;
     847}
     848#endif /* MBS_SUPPORT */
     849
    514850EXECUTE_FCT(Fexecute)
    515851{
    516852  register char const *beg, *try, *end;
     
    519855  struct kwsmatch kwsmatch;
    520856  size_t ret_val;
    521857#ifdef MBS_SUPPORT
    522   char *mb_properties = NULL;
    523   if (MB_CUR_MAX > 1)
    524     {
    525       if (match_icase)
    526         {
    527           char *case_buf = xmalloc(size);
    528           memcpy(case_buf, buf, size);
    529           if (start_ptr)
    530             start_ptr = case_buf + (start_ptr - buf);
    531           buf = case_buf;
    532         }
    533       mb_properties = check_multibyte_string(buf, size);
    534     }
     858  int mb_cur_max = MB_CUR_MAX;
     859  mbstate_t mbs;
     860  memset (&mbs, '\0', sizeof (mbstate_t));
     861  const char *last_char = NULL;
    535862#endif /* MBS_SUPPORT */
    536863
    537864  for (beg = start_ptr ? start_ptr : buf; beg <= buf + size; beg++)
    538865    {
    539866      size_t offset = kwsexec (kwset, beg, buf + size - beg, &kwsmatch);
    540867      if (offset == (size_t) -1)
    541         goto failure;
     868        return offset;
    542869#ifdef MBS_SUPPORT
    543       if (MB_CUR_MAX > 1 && mb_properties[offset+beg-buf] == 0)
    544         continue; /* It is a part of multibyte character.  */
     870      if (mb_cur_max > 1 && !using_utf8)
     871        {
     872          size_t bytes_left = offset;
     873          while (bytes_left)
     874            {
     875              size_t mlen = mbrlen (beg, bytes_left, &mbs);
     876
     877              last_char = beg;
     878              if (mlen == (size_t) -1 || mlen == 0)
     879                {
     880                  /* Incomplete character: treat as single-byte. */
     881                  memset (&mbs, '\0', sizeof (mbstate_t));
     882                  beg++;
     883                  bytes_left--;
     884                  continue;
     885                }
     886
     887              if (mlen == (size_t) -2)
     888                /* Offset points inside multibyte character: no good. */
     889                break;
     890
     891              beg += mlen;
     892              bytes_left -= mlen;
     893            }
     894
     895          if (bytes_left)
     896            continue;
     897        }
     898      else
    545899#endif /* MBS_SUPPORT */
    546900      beg += offset;
     901#ifdef MBS_SUPPORT
     902      /* For f_i_multibyte, the string at beg now matches first 3 chars of
     903         one of the search strings (less if there are shorter search strings).
     904         See if this is a real match.  */
     905      if (f_i_multibyte
     906          && Fimbexec (beg, buf + size - beg, &kwsmatch.size[0], start_ptr == NULL))
     907        goto next_char;
     908#endif /* MBS_SUPPORT */
    547909      len = kwsmatch.size[0];
    548910      if (start_ptr && !match_words)
    549911        goto success_in_beg_and_len;
    550912      if (match_lines)
    551913        {
    552914          if (beg > buf && beg[-1] != eol)
    553             continue;
     915            goto next_char;
    554916          if (beg + len < buf + size && beg[len] != eol)
    555             continue;
     917            goto next_char;
    556918          goto success;
    557919        }
    558920      else if (match_words)
    559         for (try = beg; len; )
    560           {
    561             if (try > buf && WCHAR((unsigned char) try[-1]))
    562               break;
    563             if (try + len < buf + size && WCHAR((unsigned char) try[len]))
    564               {
    565                 offset = kwsexec (kwset, beg, --len, &kwsmatch);
    566                 if (offset == (size_t) -1)
    567                   break;
    568                 try = beg + offset;
    569                 len = kwsmatch.size[0];
    570               }
    571             else if (!start_ptr)
    572               goto success;
    573             else
    574               goto success_in_beg_and_len;
    575           } /* for (try) */
    576       else
     921        {
     922          while (len)
     923            {
     924              int word_match = 0;
     925              if (beg > buf)
     926                {
     927#ifdef MBS_SUPPORT
     928                  if (mb_cur_max > 1)
     929                    {
     930                      const char *s;
     931                      int mr;
     932                      wchar_t pwc;
     933
     934                      if (using_utf8)
     935                        {
     936                          s = beg - 1;
     937                          while (s > buf
     938                                 && (unsigned char) *s >= 0x80
     939                                 && (unsigned char) *s <= 0xbf)
     940                            --s;
     941                        }
     942                      else
     943                        s = last_char;
     944                      mr = mbtowc (&pwc, s, beg - s);
     945                      if (mr <= 0)
     946                        memset (&mbs, '\0', sizeof (mbstate_t));
     947                      else if ((iswalnum (pwc) || pwc == L'_')
     948                               && mr == (int) (beg - s))
     949                        goto next_char;
     950                    }
     951                  else
     952#endif /* MBS_SUPPORT */
     953                  if (WCHAR ((unsigned char) beg[-1]))
     954                    goto next_char;
     955                }
     956#ifdef MBS_SUPPORT
     957              if (mb_cur_max > 1)
     958                {
     959                  wchar_t nwc;
     960                  int mr;
     961
     962                  mr = mbtowc (&nwc, beg + len, buf + size - beg - len);
     963                  if (mr <= 0)
     964                    {
     965                      memset (&mbs, '\0', sizeof (mbstate_t));
     966                      word_match = 1;
     967                    }
     968                  else if (!iswalnum (nwc) && nwc != L'_')
     969                    word_match = 1;
     970                }
     971              else
     972#endif /* MBS_SUPPORT */
     973                if (beg + len >= buf + size || !WCHAR ((unsigned char) beg[len]))
     974                  word_match = 1;
     975              if (word_match)
     976                {
     977                  if (start_ptr == NULL)
     978                    /* Returns the whole line now we know there's a word match. */
     979                    goto success;
     980                  else {
     981                    /* Returns just this word match. */
     982                    *match_size = len;
     983                    return beg - buf;
     984                  }
     985                }
     986              if (len > 0)
     987                {
     988                  /* Try a shorter length anchored at the same place. */
     989                  --len;
     990                  offset = kwsexec (kwset, beg, len, &kwsmatch);
     991
     992                  if (offset == -1)
     993                    goto next_char; /* Try a different anchor. */
     994#ifdef MBS_SUPPORT
     995
     996                  if (mb_cur_max > 1 && !using_utf8)
     997                    {
     998                      size_t bytes_left = offset;
     999                      while (bytes_left)
     1000                        {
     1001                          size_t mlen = mbrlen (beg, bytes_left, &mbs);
     1002
     1003                          last_char = beg;
     1004                          if (mlen == (size_t) -1 || mlen == 0)
     1005                            {
     1006                              /* Incomplete character: treat as single-byte. */
     1007                              memset (&mbs, '\0', sizeof (mbstate_t));
     1008                              beg++;
     1009                              bytes_left--;
     1010                              continue;
     1011                            }
     1012
     1013                          if (mlen == (size_t) -2)
     1014                            {
     1015                              /* Offset points inside multibyte character:
     1016                               * no good. */
     1017                              break;
     1018                            }
     1019
     1020                          beg += mlen;
     1021                          bytes_left -= mlen;
     1022                        }
     1023
     1024                      if (bytes_left)
     1025                        {
     1026                          memset (&mbs, '\0', sizeof (mbstate_t));
     1027                          goto next_char; /* Try a different anchor. */
     1028                        }
     1029                    }
     1030                  else
     1031#endif /* MBS_SUPPORT */
     1032                  beg += offset;
     1033#ifdef MBS_SUPPORT
     1034                  /* The string at beg now matches first 3 chars of one of
     1035                     the search strings (less if there are shorter search
     1036                     strings).  See if this is a real match.  */
     1037                  if (f_i_multibyte
     1038                      && Fimbexec (beg, len - offset, &kwsmatch.size[0],
     1039                                   start_ptr == NULL))
     1040                    goto next_char;
     1041#endif /* MBS_SUPPORT */
     1042                  len = kwsmatch.size[0];
     1043                }
     1044            }
     1045        }
     1046       else
    5771047        goto success;
    578     } /* for (beg in buf) */
     1048next_char:;
     1049#ifdef MBS_SUPPORT
     1050      /* Advance to next character.  For MB_CUR_MAX == 1 case this is handled
     1051         by ++beg above.  */
     1052      if (mb_cur_max > 1)
     1053        {
     1054          if (using_utf8)
     1055            {
     1056              unsigned char c = *beg;
     1057              if (c >= 0xc2)
     1058                {
     1059                  if (c < 0xe0)
     1060                    ++beg;
     1061                  else if (c < 0xf0)
     1062                    beg += 2;
     1063                  else if (c < 0xf8)
     1064                    beg += 3;
     1065                  else if (c < 0xfc)
     1066                    beg += 4;
     1067                  else if (c < 0xfe)
     1068                    beg += 5;
     1069                }
     1070            }
     1071          else
     1072            {
     1073              size_t l = mbrlen (beg, buf + size - beg, &mbs);
    5791074
    580  failure:
    581   ret_val = -1;
    582   goto out;
     1075              last_char = beg;
     1076              if (l + 2 >= 2)
     1077                beg += l - 1;
     1078              else
     1079                memset (&mbs, '\0', sizeof (mbstate_t));
     1080            }
     1081        }
     1082#endif /* MBS_SUPPORT */
     1083    }
     1084
     1085  return -1;
    5831086
    5841087 success:
     1088#ifdef MBS_SUPPORT
     1089  if (mb_cur_max > 1 && !using_utf8)
     1090    {
     1091      end = beg + len;
     1092      while (end < buf + size)
     1093        {
     1094          size_t mlen = mbrlen (end, buf + size - end, &mbs);
     1095          if (mlen == (size_t) -1 || mlen == (size_t) -2 || mlen == 0)
     1096            {
     1097              memset (&mbs, '\0', sizeof (mbstate_t));
     1098              mlen = 1;
     1099            }
     1100          if (mlen == 1 && *end == eol)
     1101            break;
     1102
     1103          end += mlen;
     1104        }
     1105     }
     1106  else
     1107 #endif /* MBS_SUPPORT */
    5851108  end = memchr (beg + len, eol, (buf + size) - (beg + len));
    5861109  end++;
    5871110  while (buf < beg && beg[-1] != eol)
     
    5911114  *match_size = len;
    5921115  ret_val = beg - buf;
    5931116 out:
    594 #ifdef MBS_SUPPORT
    595   if (MB_CUR_MAX > 1)
    596     {
    597       if (match_icase)
    598         free((char*)buf);
    599       if (mb_properties)
    600         free(mb_properties);
    601     }
    602 #endif /* MBS_SUPPORT */
    6031117  return ret_val;
    6041118}
    6051119#endif /* defined(GREP_PROGRAM) || defined(FGREP_PROGRAM) */
Note: See TracBrowser for help on using the repository browser.