(root)/
glibc-2.38/
posix/
bug-regex19.c
       1  /* Regular expression tests.
       2     Copyright (C) 2003-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <sys/types.h>
      20  #include <mcheck.h>
      21  #include <regex.h>
      22  #include <stdio.h>
      23  #include <stdlib.h>
      24  #include <string.h>
      25  #include <locale.h>
      26  #include <libc-diag.h>
      27  #include <support/support.h>
      28  
      29  #define BRE RE_SYNTAX_POSIX_BASIC
      30  #define ERE RE_SYNTAX_POSIX_EXTENDED
      31  
      32  static struct test_s
      33  {
      34    int syntax;
      35    const char *pattern;
      36    const char *string;
      37    int start, res;
      38  } tests[] = {
      39    {BRE, "\\<A", "CBAA", 0, -1},
      40    {BRE, "\\<A", "CBAA", 2, -1},
      41    {BRE, "A\\>", "CAAB", 1, -1},
      42    {BRE, "\\bA", "CBAA", 0, -1},
      43    {BRE, "\\bA", "CBAA", 2, -1},
      44    {BRE, "A\\b", "CAAB", 1, -1},
      45    {BRE, "\\<A", "AA", 0, 0},
      46    {BRE, "\\<A", "C-AA", 2, 2},
      47    {BRE, "A\\>", "CAA-", 1, 2},
      48    {BRE, "A\\>", "CAA", 1, 2},
      49    {BRE, "\\bA", "AA", 0, 0},
      50    {BRE, "\\bA", "C-AA", 2, 2},
      51    {BRE, "A\\b", "CAA-", 1, 2},
      52    {BRE, "A\\b", "CAA", 1, 2},
      53    {BRE, "\\<[A]", "CBAA", 0, -1},
      54    {BRE, "\\<[A]", "CBAA", 2, -1},
      55    {BRE, "[A]\\>", "CAAB", 1, -1},
      56    {BRE, "\\b[A]", "CBAA", 0, -1},
      57    {BRE, "\\b[A]", "CBAA", 2, -1},
      58    {BRE, "[A]\\b", "CAAB", 1, -1},
      59    {BRE, "\\<[A]", "AA", 0, 0},
      60    {BRE, "\\<[A]", "C-AA", 2, 2},
      61    {BRE, "[A]\\>", "CAA-", 1, 2},
      62    {BRE, "[A]\\>", "CAA", 1, 2},
      63    {BRE, "\\b[A]", "AA", 0, 0},
      64    {BRE, "\\b[A]", "C-AA", 2, 2},
      65    {BRE, "[A]\\b", "CAA-", 1, 2},
      66    {BRE, "[A]\\b", "CAA", 1, 2},
      67    {ERE, "\\b(A|!|.B)", "A=AC", 0, 0},
      68    {ERE, "\\b(A|!|.B)", "=AC", 0, 1},
      69    {ERE, "\\b(A|!|.B)", "!AC", 0, 1},
      70    {ERE, "\\b(A|!|.B)", "=AB", 0, 1},
      71    {ERE, "\\b(A|!|.B)", "DA!C", 0, 2},
      72    {ERE, "\\b(A|!|.B)", "=CB", 0, 1},
      73    {ERE, "\\b(A|!|.B)", "!CB", 0, 1},
      74    {ERE, "\\b(A|!|.B)", "D,B", 0, 1},
      75    {ERE, "\\b(A|!|.B)", "!.C", 0, -1},
      76    {ERE, "\\b(A|!|.B)", "BCB", 0, -1},
      77    {ERE, "(A|\\b)(A|B|C)", "DAAD", 0, 1},
      78    {ERE, "(A|\\b)(A|B|C)", "DABD", 0, 1},
      79    {ERE, "(A|\\b)(A|B|C)", "AD", 0, 0},
      80    {ERE, "(A|\\b)(A|B|C)", "C!", 0, 0},
      81    {ERE, "(A|\\b)(A|B|C)", "D,B", 0, 2},
      82    {ERE, "(A|\\b)(A|B|C)", "DA?A", 0, 3},
      83    {ERE, "(A|\\b)(A|B|C)", "BBC", 0, 0},
      84    {ERE, "(A|\\b)(A|B|C)", "DA", 0, -1},
      85    {ERE, "(!|\\b)(!|=|~)", "A!=\\", 0, 1},
      86    {ERE, "(!|\\b)(!|=|~)", "/!=A", 0, 1},
      87    {ERE, "(!|\\b)(!|=|~)", "A=A", 0, 1},
      88    {ERE, "(!|\\b)(!|=|~)", "==!=", 0, 2},
      89    {ERE, "(!|\\b)(!|=|~)", "==C~", 0, 3},
      90    {ERE, "(!|\\b)(!|=|~)", "=~=", 0, -1},
      91    {ERE, "(!|\\b)(!|=|~)", "~!", 0, -1},
      92    {ERE, "(!|\\b)(!|=|~)", "~=~", 0, -1},
      93    {ERE, "(\\b|A.)[ABC]", "AC", 0, 0},
      94    {ERE, "(\\b|A.)[ABC]", "=A", 0, 1},
      95    {ERE, "(\\b|A.)[ABC]", "DACC", 0, 1},
      96    {ERE, "(\\b|A.)[A~C]", "AC", 0, 0},
      97    {ERE, "(\\b|A.)[A~C]", "=A", 0, 1},
      98    {ERE, "(\\b|A.)[A~C]", "DACC", 0, 1},
      99    {ERE, "(\\b|A.)[A~C]", "B!A=", 0, 2},
     100    {ERE, "(\\b|A.)[A~C]", "B~C", 0, 1},
     101    {ERE, ".\\b.", "AA~", 0, 1},
     102    {ERE, ".\\b.", "=A=", 0, 0},
     103    {ERE, ".\\b.", "==", 0, -1},
     104    {ERE, ".\\b.", "ABA", 0, -1},
     105    {ERE, "[^k]\\b[^k]", "AA~", 0, 1},
     106    {ERE, "[^k]\\b[^k]", "=A=", 0, 0},
     107    {ERE, "[^k]\\b[^k]", "Ak~kA~", 0, 4},
     108    {ERE, "[^k]\\b[^k]", "==", 0, -1},
     109    {ERE, "[^k]\\b[^k]", "ABA", 0, -1},
     110    {ERE, "[^k]\\b[^k]", "Ak~", 0, -1},
     111    {ERE, "[^k]\\b[^k]", "k=k", 0, -1},
     112    {ERE, "[^C]\\b[^C]", "AA~", 0, 1},
     113    {ERE, "[^C]\\b[^C]", "=A=", 0, 0},
     114    {ERE, "[^C]\\b[^C]", "AC~CA~", 0, 4},
     115    {ERE, "[^C]\\b[^C]", "==", 0, -1},
     116    {ERE, "[^C]\\b[^C]", "ABA", 0, -1},
     117    {ERE, "[^C]\\b[^C]", "AC~", 0, -1},
     118    {ERE, "[^C]\\b[^C]", "C=C", 0, -1},
     119    {ERE, "\\<(A|!|.B)", "A=AC", 0, 0},
     120    {ERE, "\\<(A|!|.B)", "=AC", 0, 1},
     121    {ERE, "\\<(A|!|.B)", "!AC", 0, 1},
     122    {ERE, "\\<(A|!|.B)", "=AB", 0, 1},
     123    {ERE, "\\<(A|!|.B)", "=CB", 0, 1},
     124    {ERE, "\\<(A|!|.B)", "!CB", 0, 1},
     125    {ERE, "\\<(A|!|.B)", "DA!C", 0, -1},
     126    {ERE, "\\<(A|!|.B)", "D,B", 0, -1},
     127    {ERE, "\\<(A|!|.B)", "!.C", 0, -1},
     128    {ERE, "\\<(A|!|.B)", "BCB", 0, -1},
     129    {ERE, "(A|\\<)(A|B|C)", "DAAD", 0, 1},
     130    {ERE, "(A|\\<)(A|B|C)", "DABD", 0, 1},
     131    {ERE, "(A|\\<)(A|B|C)", "AD", 0, 0},
     132    {ERE, "(A|\\<)(A|B|C)", "C!", 0, 0},
     133    {ERE, "(A|\\<)(A|B|C)", "D,B", 0, 2},
     134    {ERE, "(A|\\<)(A|B|C)", "DA?A", 0, 3},
     135    {ERE, "(A|\\<)(A|B|C)", "BBC", 0, 0},
     136    {ERE, "(A|\\<)(A|B|C)", "DA", 0, -1},
     137    {ERE, "(!|\\<)(!|=|~)", "A!=\\", 0, 1},
     138    {ERE, "(!|\\<)(!|=|~)", "/!=A", 0, 1},
     139    {ERE, "(!|\\<)(!|=|~)", "==!=", 0, 2},
     140    {ERE, "(!|\\<)(!|=|~)", "==C~", 0, -1},
     141    {ERE, "(!|\\<)(!|=|~)", "A=A", 0, -1},
     142    {ERE, "(!|\\<)(!|=|~)", "=~=", 0, -1},
     143    {ERE, "(!|\\<)(!|=|~)", "~!", 0, -1},
     144    {ERE, "(!|\\<)(!|=|~)", "~=~", 0, -1},
     145    {ERE, "(\\<|A.)[ABC]", "AC", 0, 0},
     146    {ERE, "(\\<|A.)[ABC]", "=A", 0, 1},
     147    {ERE, "(\\<|A.)[ABC]", "DACC", 0, 1},
     148    {ERE, "(\\<|A.)[A~C]", "AC", 0, 0},
     149    {ERE, "(\\<|A.)[A~C]", "=A", 0, 1},
     150    {ERE, "(\\<|A.)[A~C]", "DACC", 0, 1},
     151    {ERE, "(\\<|A.)[A~C]", "B!A=", 0, 2},
     152    {ERE, "(\\<|A.)[A~C]", "B~C", 0, 2},
     153    {ERE, ".\\<.", "=A=", 0, 0},
     154    {ERE, ".\\<.", "AA~", 0, -1},
     155    {ERE, ".\\<.", "==", 0, -1},
     156    {ERE, ".\\<.", "ABA", 0, -1},
     157    {ERE, "[^k]\\<[^k]", "=k=A=", 0, 2},
     158    {ERE, "[^k]\\<[^k]", "kk~", 0, -1},
     159    {ERE, "[^k]\\<[^k]", "==", 0, -1},
     160    {ERE, "[^k]\\<[^k]", "ABA", 0, -1},
     161    {ERE, "[^k]\\<[^k]", "=k=", 0, -1},
     162    {ERE, "[^C]\\<[^C]", "=C=A=", 0, 2},
     163    {ERE, "[^C]\\<[^C]", "CC~", 0, -1},
     164    {ERE, "[^C]\\<[^C]", "==", 0, -1},
     165    {ERE, "[^C]\\<[^C]", "ABA", 0, -1},
     166    {ERE, "[^C]\\<[^C]", "=C=", 0, -1},
     167    {ERE, ".\\B.", "ABA", 0, 0},
     168    {ERE, ".\\B.", "=BDC", 0, 1},
     169    {ERE, "[^k]\\B[^k]", "kkkABA", 0, 3},
     170    {ERE, "[^k]\\B[^k]", "kBk", 0, -1},
     171    {ERE, "[^C]\\B[^C]", "CCCABA", 0, 3},
     172    {ERE, "[^C]\\B[^C]", "CBC", 0, -1},
     173    {ERE, ".(\\b|\\B).", "=~AB", 0, 0},
     174    {ERE, ".(\\b|\\B).", "A=C", 0, 0},
     175    {ERE, ".(\\b|\\B).", "ABC", 0, 0},
     176    {ERE, ".(\\b|\\B).", "=~\\!", 0, 0},
     177    {ERE, "[^k](\\b|\\B)[^k]", "=~AB", 0, 0},
     178    {ERE, "[^k](\\b|\\B)[^k]", "A=C", 0, 0},
     179    {ERE, "[^k](\\b|\\B)[^k]", "ABC", 0, 0},
     180    {ERE, "[^k](\\b|\\B)[^k]", "=~kBD", 0, 0},
     181    {ERE, "[^k](\\b|\\B)[^k]", "=~\\!", 0, 0},
     182    {ERE, "[^k](\\b|\\B)[^k]", "=~kB", 0, 0},
     183    {ERE, "[^C](\\b|\\B)[^C]", "=~AB", 0, 0},
     184    {ERE, "[^C](\\b|\\B)[^C]", "A=C", 0, 0},
     185    {ERE, "[^C](\\b|\\B)[^C]", "ABC", 0, 0},
     186    {ERE, "[^C](\\b|\\B)[^C]", "=~CBD", 0, 0},
     187    {ERE, "[^C](\\b|\\B)[^C]", "=~\\!", 0, 0},
     188    {ERE, "[^C](\\b|\\B)[^C]", "=~CB", 0, 0},
     189    {ERE, "\\b([A]|[!]|.B)", "A=AC", 0, 0},
     190    {ERE, "\\b([A]|[!]|.B)", "=AC", 0, 1},
     191    {ERE, "\\b([A]|[!]|.B)", "!AC", 0, 1},
     192    {ERE, "\\b([A]|[!]|.B)", "=AB", 0, 1},
     193    {ERE, "\\b([A]|[!]|.B)", "DA!C", 0, 2},
     194    {ERE, "\\b([A]|[!]|.B)", "=CB", 0, 1},
     195    {ERE, "\\b([A]|[!]|.B)", "!CB", 0, 1},
     196    {ERE, "\\b([A]|[!]|.B)", "D,B", 0, 1},
     197    {ERE, "\\b([A]|[!]|.B)", "!.C", 0, -1},
     198    {ERE, "\\b([A]|[!]|.B)", "BCB", 0, -1},
     199    {ERE, "([A]|\\b)([A]|[B]|[C])", "DAAD", 0, 1},
     200    {ERE, "([A]|\\b)([A]|[B]|[C])", "DABD", 0, 1},
     201    {ERE, "([A]|\\b)([A]|[B]|[C])", "AD", 0, 0},
     202    {ERE, "([A]|\\b)([A]|[B]|[C])", "C!", 0, 0},
     203    {ERE, "([A]|\\b)([A]|[B]|[C])", "D,B", 0, 2},
     204    {ERE, "([A]|\\b)([A]|[B]|[C])", "DA?A", 0, 3},
     205    {ERE, "([A]|\\b)([A]|[B]|[C])", "BBC", 0, 0},
     206    {ERE, "([A]|\\b)([A]|[B]|[C])", "DA", 0, -1},
     207    {ERE, "([!]|\\b)([!]|[=]|[~])", "A!=\\", 0, 1},
     208    {ERE, "([!]|\\b)([!]|[=]|[~])", "/!=A", 0, 1},
     209    {ERE, "([!]|\\b)([!]|[=]|[~])", "A=A", 0, 1},
     210    {ERE, "([!]|\\b)([!]|[=]|[~])", "==!=", 0, 2},
     211    {ERE, "([!]|\\b)([!]|[=]|[~])", "==C~", 0, 3},
     212    {ERE, "([!]|\\b)([!]|[=]|[~])", "=~=", 0, -1},
     213    {ERE, "([!]|\\b)([!]|[=]|[~])", "~!", 0, -1},
     214    {ERE, "([!]|\\b)([!]|[=]|[~])", "~=~", 0, -1},
     215    {ERE, "\\<([A]|[!]|.B)", "A=AC", 0, 0},
     216    {ERE, "\\<([A]|[!]|.B)", "=AC", 0, 1},
     217    {ERE, "\\<([A]|[!]|.B)", "!AC", 0, 1},
     218    {ERE, "\\<([A]|[!]|.B)", "=AB", 0, 1},
     219    {ERE, "\\<([A]|[!]|.B)", "=CB", 0, 1},
     220    {ERE, "\\<([A]|[!]|.B)", "!CB", 0, 1},
     221    {ERE, "\\<([A]|[!]|.B)", "DA!C", 0, -1},
     222    {ERE, "\\<([A]|[!]|.B)", "D,B", 0, -1},
     223    {ERE, "\\<([A]|[!]|.B)", "!.C", 0, -1},
     224    {ERE, "\\<([A]|[!]|.B)", "BCB", 0, -1},
     225    {ERE, "([A]|\\<)([A]|[B]|[C])", "DAAD", 0, 1},
     226    {ERE, "([A]|\\<)([A]|[B]|[C])", "DABD", 0, 1},
     227    {ERE, "([A]|\\<)([A]|[B]|[C])", "AD", 0, 0},
     228    {ERE, "([A]|\\<)([A]|[B]|[C])", "C!", 0, 0},
     229    {ERE, "([A]|\\<)([A]|[B]|[C])", "D,B", 0, 2},
     230    {ERE, "([A]|\\<)([A]|[B]|[C])", "DA?A", 0, 3},
     231    {ERE, "([A]|\\<)([A]|[B]|[C])", "BBC", 0, 0},
     232    {ERE, "([A]|\\<)([A]|[B]|[C])", "DA", 0, -1},
     233    {ERE, "([!]|\\<)([!=]|[~])", "A!=\\", 0, 1},
     234    {ERE, "([!]|\\<)([!=]|[~])", "/!=A", 0, 1},
     235    {ERE, "([!]|\\<)([!=]|[~])", "==!=", 0, 2},
     236    {ERE, "([!]|\\<)([!=]|[~])", "==C~", 0, -1},
     237    {ERE, "([!]|\\<)([!=]|[~])", "A=A", 0, -1},
     238    {ERE, "([!]|\\<)([!=]|[~])", "=~=", 0, -1},
     239    {ERE, "([!]|\\<)([!=]|[~])", "~!", 0, -1},
     240    {ERE, "([!]|\\<)([!=]|[~])", "~=~", 0, -1},
     241    {ERE, "(\\<|[A].)[ABC]", "AC", 0, 0},
     242    {ERE, "(\\<|[A].)[ABC]", "=A", 0, 1},
     243    {ERE, "(\\<|[A].)[ABC]", "DACC", 0, 1},
     244    {ERE, "(\\<|[A].)[A~C]", "AC", 0, 0},
     245    {ERE, "(\\<|[A].)[A~C]", "=A", 0, 1},
     246    {ERE, "(\\<|[A].)[A~C]", "DACC", 0, 1},
     247    {ERE, "(\\<|[A].)[A~C]", "B!A=", 0, 2},
     248    {ERE, "(\\<|[A].)[A~C]", "B~C", 0, 2},
     249    {ERE, "^[^A]*\\bB", "==B", 0, 0},
     250    {ERE, "^[^A]*\\bB", "CBD!=B", 0, 0},
     251    {ERE, "[^A]*\\bB", "==B", 2, 2}
     252  };
     253  
     254  int
     255  do_one_test (const struct test_s *test, const char *fail)
     256  {
     257    int res;
     258    const char *err;
     259    struct re_pattern_buffer regbuf;
     260  
     261    re_set_syntax (test->syntax);
     262    memset (&regbuf, '\0', sizeof (regbuf));
     263    err = re_compile_pattern (test->pattern, strlen (test->pattern),
     264  			    &regbuf);
     265    if (err != NULL)
     266      {
     267        printf ("%sre_compile_pattern \"%s\" failed: %s\n", fail, test->pattern,
     268  	      err);
     269        return 1;
     270      }
     271  
     272  #if __GNUC_PREREQ (10, 0) && !__GNUC_PREREQ (11, 0)
     273    DIAG_PUSH_NEEDS_COMMENT;
     274    /* Avoid GCC 10 false positive warning: specified size exceeds maximum
     275       object size.  */
     276    DIAG_IGNORE_NEEDS_COMMENT (10, "-Wstringop-overflow");
     277  #endif
     278    res = re_search (&regbuf, test->string, strlen (test->string),
     279  		   test->start, strlen (test->string) - test->start, NULL);
     280  #if __GNUC_PREREQ (10, 0) && !__GNUC_PREREQ (11, 0)
     281    DIAG_POP_NEEDS_COMMENT;
     282  #endif
     283    if (res != test->res)
     284      {
     285        printf ("%sre_search \"%s\" \"%s\" failed: %d (expected %d)\n",
     286  	      fail, test->pattern, test->string, res, test->res);
     287        regfree (&regbuf);
     288        return 1;
     289      }
     290  
     291    if (test->res > 0 && test->start == 0)
     292      {
     293  #if __GNUC_PREREQ (10, 0) && !__GNUC_PREREQ (11, 0)
     294    DIAG_PUSH_NEEDS_COMMENT;
     295    /* Avoid GCC 10 false positive warning: specified size exceeds maximum
     296       object size.  */
     297    DIAG_IGNORE_NEEDS_COMMENT (10, "-Wstringop-overflow");
     298  #endif
     299        res = re_search (&regbuf, test->string, strlen (test->string),
     300  		       test->res, strlen (test->string) - test->res, NULL);
     301  #if __GNUC_PREREQ (10, 0) && !__GNUC_PREREQ (11, 0)
     302    DIAG_POP_NEEDS_COMMENT;
     303  #endif
     304        if (res != test->res)
     305  	{
     306  	  printf ("%sre_search from expected \"%s\" \"%s\" failed: %d (expected %d)\n",
     307  		  fail, test->pattern, test->string, res, test->res);
     308  	  regfree (&regbuf);
     309  	  return 1;
     310  	}
     311      }
     312  
     313    regfree (&regbuf);
     314    return 0;
     315  }
     316  
     317  static char *
     318  replace (char *p, char c)
     319  {
     320    switch (c)
     321      {
     322        /* A -> A" */
     323        case 'A': *p++ = '\xc3'; *p++ = '\x84'; break;
     324        /* B -> O" */
     325        case 'B': *p++ = '\xc3'; *p++ = '\x96'; break;
     326        /* C -> U" */
     327        case 'C': *p++ = '\xc3'; *p++ = '\x9c'; break;
     328        /* D -> a" */
     329        case 'D': *p++ = '\xc3'; *p++ = '\xa4'; break;
     330        /* ! -> MULTIPLICATION SIGN */
     331        case '!': *p++ = '\xc3'; *p++ = '\x97'; break;
     332        /* = -> EM DASH */
     333        case '=': *p++ = '\xe2'; *p++ = '\x80'; *p++ = '\x94'; break;
     334        /* ~ -> MUSICAL SYMBOL HALF NOTE */
     335        case '~': *p++ = '\xf0'; *p++ = '\x9d'; *p++ = '\x85'; *p++ = '\x9e';
     336        break;
     337      }
     338    return p;
     339  }
     340  
     341  int
     342  do_mb_tests (const struct test_s *test)
     343  {
     344    int i, j;
     345    struct test_s t;
     346    const char *const chars = "ABCD!=~";
     347    char repl[8], *p;
     348    char pattern[strlen (test->pattern) * 4 + 1];
     349    char string[strlen (test->string) * 4 + 1];
     350    char fail[8 + sizeof ("UTF-8 ")];
     351  
     352    t = *test;
     353    t.pattern = pattern;
     354    t.string = string;
     355    strcpy (fail, "UTF-8 ");
     356    for (i = 1; i < 128; ++i)
     357      {
     358        p = repl;
     359        for (j = 0; j < 7; ++j)
     360  	if (i & (1 << j))
     361  	  {
     362  	    if (!strchr (test->pattern, chars[j])
     363  		&& !strchr (test->string, chars[j]))
     364  	      break;
     365  	    *p++ = chars[j];
     366  	  }
     367        if (j < 7)
     368  	continue;
     369        *p = '\0';
     370  
     371        for (j = 0, p = pattern; test->pattern[j]; ++j)
     372  	if (strchr (repl, test->pattern[j]))
     373  	  p = replace (p, test->pattern[j]);
     374  	else if (test->pattern[j] == '\\' && test->pattern[j + 1])
     375  	  {
     376  	    *p++ = test->pattern[j++];
     377  	    *p++ = test->pattern[j];
     378  	  }
     379  	else
     380  	  *p++ = test->pattern[j];
     381        *p = '\0';
     382  
     383        t.start = test->start;
     384        t.res = test->res;
     385  
     386        for (j = 0, p = string; test->string[j]; ++j)
     387  	if (strchr (repl, test->string[j]))
     388  	  {
     389  	    char *d = replace (p, test->string[j]);
     390  	    if (test->start > j)
     391  	      t.start += d - p - 1;
     392  	    if (test->res > j)
     393  	      t.res += d - p - 1;
     394  	    p = d;
     395  	  }
     396  	else
     397  	  *p++ = test->string[j];
     398        *p = '\0';
     399  
     400        p = stpcpy (fail + strlen ("UTF-8 "), repl);
     401        *p++ = ' ';
     402        *p = '\0';
     403  
     404        if (do_one_test (&t, fail))
     405  	return 1;
     406      }
     407    return 0;
     408  }
     409  
     410  static int
     411  do_test (void)
     412  {
     413    size_t i;
     414    int ret = 0;
     415  
     416    mtrace ();
     417  
     418    for (i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i)
     419      {
     420        xsetlocale (LC_ALL, "de_DE.ISO-8859-1");
     421        ret |= do_one_test (&tests[i], "");
     422        xsetlocale (LC_ALL, "de_DE.UTF-8");
     423        ret |= do_one_test (&tests[i], "UTF-8 ");
     424        ret |= do_mb_tests (&tests[i]);
     425        xsetlocale (LC_ALL, "C.UTF-8");
     426        ret |= do_one_test (&tests[i], "UTF-8 ");
     427        ret |= do_mb_tests (&tests[i]);
     428      }
     429  
     430    return ret;
     431  }
     432  
     433  #include <support/test-driver.c>