1206710Sjilles/*- 2206710Sjilles * Copyright (c) 2010 Jilles Tjoelker 3206710Sjilles * All rights reserved. 4206710Sjilles * 5206710Sjilles * Redistribution and use in source and binary forms, with or without 6206710Sjilles * modification, are permitted provided that the following conditions 7206710Sjilles * are met: 8206710Sjilles * 1. Redistributions of source code must retain the above copyright 9206710Sjilles * notice, this list of conditions and the following disclaimer. 10206710Sjilles * 2. Redistributions in binary form must reproduce the above copyright 11206710Sjilles * notice, this list of conditions and the following disclaimer in the 12206710Sjilles * documentation and/or other materials provided with the distribution. 13206710Sjilles * 14206710Sjilles * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15206710Sjilles * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16206710Sjilles * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17206710Sjilles * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18206710Sjilles * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19206710Sjilles * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20206710Sjilles * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21206710Sjilles * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22206710Sjilles * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23206710Sjilles * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24206710Sjilles * SUCH DAMAGE. 25206710Sjilles */ 26206710Sjilles 27206710Sjilles#include <sys/cdefs.h> 28206710Sjilles__FBSDID("$FreeBSD$"); 29206710Sjilles 30206710Sjilles#include <errno.h> 31206710Sjilles#include <stdio.h> 32206710Sjilles#include <stdlib.h> 33206710Sjilles#include <string.h> 34207821Sjilles#include <unistd.h> 35206710Sjilles#include <fnmatch.h> 36206710Sjilles 37206710Sjillesstruct testcase { 38206710Sjilles const char *pattern; 39206710Sjilles const char *string; 40206710Sjilles int flags; 41206710Sjilles int result; 42206710Sjilles} testcases[] = { 43206710Sjilles "", "", 0, 0, 44206710Sjilles "a", "a", 0, 0, 45206710Sjilles "a", "b", 0, FNM_NOMATCH, 46206710Sjilles "a", "A", 0, FNM_NOMATCH, 47206710Sjilles "*", "a", 0, 0, 48206710Sjilles "*", "aa", 0, 0, 49206710Sjilles "*a", "a", 0, 0, 50206710Sjilles "*a", "b", 0, FNM_NOMATCH, 51206710Sjilles "*a*", "b", 0, FNM_NOMATCH, 52206710Sjilles "*a*b*", "ab", 0, 0, 53206710Sjilles "*a*b*", "qaqbq", 0, 0, 54206710Sjilles "*a*bb*", "qaqbqbbq", 0, 0, 55206710Sjilles "*a*bc*", "qaqbqbcq", 0, 0, 56206710Sjilles "*a*bb*", "qaqbqbb", 0, 0, 57206710Sjilles "*a*bc*", "qaqbqbc", 0, 0, 58206710Sjilles "*a*bb", "qaqbqbb", 0, 0, 59206710Sjilles "*a*bc", "qaqbqbc", 0, 0, 60206710Sjilles "*a*bb", "qaqbqbbq", 0, FNM_NOMATCH, 61206710Sjilles "*a*bc", "qaqbqbcq", 0, FNM_NOMATCH, 62206710Sjilles "*a*a*a*a*a*a*a*a*a*a*", "aaaaaaaaa", 0, FNM_NOMATCH, 63206710Sjilles "*a*a*a*a*a*a*a*a*a*a*", "aaaaaaaaaa", 0, 0, 64206710Sjilles "*a*a*a*a*a*a*a*a*a*a*", "aaaaaaaaaaa", 0, 0, 65206710Sjilles ".*.*.*.*.*.*.*.*.*.*", ".........", 0, FNM_NOMATCH, 66206710Sjilles ".*.*.*.*.*.*.*.*.*.*", "..........", 0, 0, 67206710Sjilles ".*.*.*.*.*.*.*.*.*.*", "...........", 0, 0, 68206710Sjilles "*?*?*?*?*?*?*?*?*?*?*", "123456789", 0, FNM_NOMATCH, 69206710Sjilles "??????????*", "123456789", 0, FNM_NOMATCH, 70206710Sjilles "*??????????", "123456789", 0, FNM_NOMATCH, 71206710Sjilles "*?*?*?*?*?*?*?*?*?*?*", "1234567890", 0, 0, 72206710Sjilles "??????????*", "1234567890", 0, 0, 73206710Sjilles "*??????????", "1234567890", 0, 0, 74206710Sjilles "*?*?*?*?*?*?*?*?*?*?*", "12345678901", 0, 0, 75206710Sjilles "??????????*", "12345678901", 0, 0, 76206710Sjilles "*??????????", "12345678901", 0, 0, 77206710Sjilles "[x]", "x", 0, 0, 78206710Sjilles "[*]", "*", 0, 0, 79206710Sjilles "[?]", "?", 0, 0, 80206710Sjilles "[", "[", 0, 0, 81206710Sjilles "[[]", "[", 0, 0, 82206710Sjilles "[[]", "x", 0, FNM_NOMATCH, 83206710Sjilles "[*]", "", 0, FNM_NOMATCH, 84206710Sjilles "[*]", "x", 0, FNM_NOMATCH, 85206710Sjilles "[?]", "x", 0, FNM_NOMATCH, 86206710Sjilles "*[*]*", "foo*foo", 0, 0, 87206710Sjilles "*[*]*", "foo", 0, FNM_NOMATCH, 88206710Sjilles "[0-9]", "0", 0, 0, 89206710Sjilles "[0-9]", "5", 0, 0, 90206710Sjilles "[0-9]", "9", 0, 0, 91206710Sjilles "[0-9]", "/", 0, FNM_NOMATCH, 92206710Sjilles "[0-9]", ":", 0, FNM_NOMATCH, 93206710Sjilles "[0-9]", "*", 0, FNM_NOMATCH, 94206710Sjilles "[!0-9]", "0", 0, FNM_NOMATCH, 95206710Sjilles "[!0-9]", "5", 0, FNM_NOMATCH, 96206710Sjilles "[!0-9]", "9", 0, FNM_NOMATCH, 97206710Sjilles "[!0-9]", "/", 0, 0, 98206710Sjilles "[!0-9]", ":", 0, 0, 99206710Sjilles "[!0-9]", "*", 0, 0, 100206710Sjilles "*[0-9]", "a0", 0, 0, 101206710Sjilles "*[0-9]", "a5", 0, 0, 102206710Sjilles "*[0-9]", "a9", 0, 0, 103206710Sjilles "*[0-9]", "a/", 0, FNM_NOMATCH, 104206710Sjilles "*[0-9]", "a:", 0, FNM_NOMATCH, 105206710Sjilles "*[0-9]", "a*", 0, FNM_NOMATCH, 106206710Sjilles "*[!0-9]", "a0", 0, FNM_NOMATCH, 107206710Sjilles "*[!0-9]", "a5", 0, FNM_NOMATCH, 108206710Sjilles "*[!0-9]", "a9", 0, FNM_NOMATCH, 109206710Sjilles "*[!0-9]", "a/", 0, 0, 110206710Sjilles "*[!0-9]", "a:", 0, 0, 111206710Sjilles "*[!0-9]", "a*", 0, 0, 112206710Sjilles "*[0-9]", "a00", 0, 0, 113206710Sjilles "*[0-9]", "a55", 0, 0, 114206710Sjilles "*[0-9]", "a99", 0, 0, 115206710Sjilles "*[0-9]", "a0a0", 0, 0, 116206710Sjilles "*[0-9]", "a5a5", 0, 0, 117206710Sjilles "*[0-9]", "a9a9", 0, 0, 118206710Sjilles "\\*", "*", 0, 0, 119206710Sjilles "\\?", "?", 0, 0, 120206710Sjilles "\\[x]", "[x]", 0, 0, 121206710Sjilles "\\[", "[", 0, 0, 122206710Sjilles "\\\\", "\\", 0, 0, 123206710Sjilles "*\\**", "foo*foo", 0, 0, 124206710Sjilles "*\\**", "foo", 0, FNM_NOMATCH, 125206710Sjilles "*\\\\*", "foo\\foo", 0, 0, 126206710Sjilles "*\\\\*", "foo", 0, FNM_NOMATCH, 127206710Sjilles "\\(", "(", 0, 0, 128206710Sjilles "\\a", "a", 0, 0, 129206710Sjilles "\\*", "a", 0, FNM_NOMATCH, 130206710Sjilles "\\?", "a", 0, FNM_NOMATCH, 131206710Sjilles "\\*", "\\*", 0, FNM_NOMATCH, 132206710Sjilles "\\?", "\\?", 0, FNM_NOMATCH, 133206710Sjilles "\\[x]", "\\[x]", 0, FNM_NOMATCH, 134206710Sjilles "\\[x]", "\\x", 0, FNM_NOMATCH, 135206710Sjilles "\\[", "\\[", 0, FNM_NOMATCH, 136206710Sjilles "\\(", "\\(", 0, FNM_NOMATCH, 137206710Sjilles "\\a", "\\a", 0, FNM_NOMATCH, 138254231Sjilles "\\", "\\", 0, FNM_NOMATCH, 139254231Sjilles "\\", "", 0, 0, 140206710Sjilles "\\*", "\\*", FNM_NOESCAPE, 0, 141206710Sjilles "\\?", "\\?", FNM_NOESCAPE, 0, 142206710Sjilles "\\", "\\", FNM_NOESCAPE, 0, 143206710Sjilles "\\\\", "\\", FNM_NOESCAPE, FNM_NOMATCH, 144206710Sjilles "\\\\", "\\\\", FNM_NOESCAPE, 0, 145206710Sjilles "*\\*", "foo\\foo", FNM_NOESCAPE, 0, 146206710Sjilles "*\\*", "foo", FNM_NOESCAPE, FNM_NOMATCH, 147206710Sjilles "*", ".", FNM_PERIOD, FNM_NOMATCH, 148206710Sjilles "?", ".", FNM_PERIOD, FNM_NOMATCH, 149206710Sjilles ".*", ".", 0, 0, 150206710Sjilles ".*", "..", 0, 0, 151206710Sjilles ".*", ".a", 0, 0, 152206710Sjilles "[0-9]", ".", FNM_PERIOD, FNM_NOMATCH, 153206710Sjilles "a*", "a.", 0, 0, 154206710Sjilles "a/a", "a/a", FNM_PATHNAME, 0, 155206710Sjilles "a/*", "a/a", FNM_PATHNAME, 0, 156206710Sjilles "*/a", "a/a", FNM_PATHNAME, 0, 157206710Sjilles "*/*", "a/a", FNM_PATHNAME, 0, 158206710Sjilles "a*b/*", "abbb/x", FNM_PATHNAME, 0, 159206710Sjilles "a*b/*", "abbb/.x", FNM_PATHNAME, 0, 160206710Sjilles "*", "a/a", FNM_PATHNAME, FNM_NOMATCH, 161206710Sjilles "*/*", "a/a/a", FNM_PATHNAME, FNM_NOMATCH, 162206710Sjilles "b/*", "b/.x", FNM_PATHNAME | FNM_PERIOD, FNM_NOMATCH, 163206710Sjilles "b*/*", "a/.x", FNM_PATHNAME | FNM_PERIOD, FNM_NOMATCH, 164206710Sjilles "b/.*", "b/.x", FNM_PATHNAME | FNM_PERIOD, 0, 165206710Sjilles "b*/.*", "b/.x", FNM_PATHNAME | FNM_PERIOD, 0, 166206710Sjilles "a", "A", FNM_CASEFOLD, 0, 167206710Sjilles "A", "a", FNM_CASEFOLD, 0, 168206710Sjilles "[a]", "A", FNM_CASEFOLD, 0, 169206710Sjilles "[A]", "a", FNM_CASEFOLD, 0, 170206710Sjilles "a", "b", FNM_CASEFOLD, FNM_NOMATCH, 171206710Sjilles "a", "a/b", FNM_PATHNAME, FNM_NOMATCH, 172206710Sjilles "*", "a/b", FNM_PATHNAME, FNM_NOMATCH, 173206710Sjilles "*b", "a/b", FNM_PATHNAME, FNM_NOMATCH, 174206710Sjilles "a", "a/b", FNM_PATHNAME | FNM_LEADING_DIR, 0, 175206710Sjilles "*", "a/b", FNM_PATHNAME | FNM_LEADING_DIR, 0, 176206710Sjilles "*", ".a/b", FNM_PATHNAME | FNM_LEADING_DIR, 0, 177206710Sjilles "*a", ".a/b", FNM_PATHNAME | FNM_LEADING_DIR, 0, 178206710Sjilles "*", ".a/b", FNM_PATHNAME | FNM_PERIOD | FNM_LEADING_DIR, FNM_NOMATCH, 179206710Sjilles "*a", ".a/b", FNM_PATHNAME | FNM_PERIOD | FNM_LEADING_DIR, FNM_NOMATCH, 180206711Sjilles "a*b/*", "abbb/.x", FNM_PATHNAME | FNM_PERIOD, FNM_NOMATCH, 181206710Sjilles}; 182206710Sjilles 183206710Sjillesstatic const char * 184206710Sjillesflags_to_string(int flags) 185206710Sjilles{ 186206710Sjilles static const int flagvalues[] = { FNM_NOESCAPE, FNM_PATHNAME, 187206710Sjilles FNM_PERIOD, FNM_LEADING_DIR, FNM_CASEFOLD, 0 }; 188206710Sjilles static const char flagnames[] = "FNM_NOESCAPE\0FNM_PATHNAME\0FNM_PERIOD\0FNM_LEADING_DIR\0FNM_CASEFOLD\0"; 189206710Sjilles static char result[sizeof(flagnames) + 3 * sizeof(int) + 2]; 190206710Sjilles char *p; 191206710Sjilles size_t i, len; 192206710Sjilles const char *fp; 193206710Sjilles 194206710Sjilles p = result; 195206710Sjilles fp = flagnames; 196206710Sjilles for (i = 0; flagvalues[i] != 0; i++) { 197206710Sjilles len = strlen(fp); 198206710Sjilles if (flags & flagvalues[i]) { 199206710Sjilles if (p != result) 200206710Sjilles *p++ = '|'; 201206710Sjilles memcpy(p, fp, len); 202206710Sjilles p += len; 203206710Sjilles flags &= ~flagvalues[i]; 204206710Sjilles } 205206710Sjilles fp += len + 1; 206206710Sjilles } 207206710Sjilles if (p == result) 208206710Sjilles memcpy(p, "0", 2); 209206710Sjilles else if (flags != 0) 210206710Sjilles sprintf(p, "%d", flags); 211206710Sjilles else 212206710Sjilles *p = '\0'; 213206710Sjilles return result; 214206710Sjilles} 215206710Sjilles 216207821Sjillesstatic int 217207821Sjilleswrite_sh_tests(const char *progname, int num) 218207821Sjilles{ 219207821Sjilles size_t i, n; 220207821Sjilles struct testcase *t; 221207821Sjilles 222207821Sjilles printf("# Generated by %s -s %d, do not edit.\n", progname, num); 223207821Sjilles printf("# $" "FreeBSD$\n"); 224207821Sjilles printf("failures=\n"); 225207821Sjilles printf("failed() { printf '%%s\\n' \"Failed: $1 '$2' '$3'\"; failures=x$failures; }\n"); 226207821Sjilles if (num == 1) { 227207821Sjilles printf("testmatch() { eval \"case \\$2 in ''$1) ;; *) failed testmatch \\\"\\$@\\\";; esac\"; }\n"); 228207821Sjilles printf("testnomatch() { eval \"case \\$2 in ''$1) failed testnomatch \\\"\\$@\\\";; esac\"; }\n"); 229207821Sjilles } else if (num == 2) { 230207821Sjilles printf("# We do not treat a backslash specially in this case,\n"); 231207821Sjilles printf("# but this is not the case in all shells.\n"); 232207821Sjilles printf("netestmatch() { case $2 in $1) ;; *) failed netestmatch \"$@\";; esac; }\n"); 233207821Sjilles printf("netestnomatch() { case $2 in $1) failed netestnomatch \"$@\";; esac; }\n"); 234207821Sjilles } 235207821Sjilles n = sizeof(testcases) / sizeof(testcases[0]); 236207821Sjilles for (i = 0; i < n; i++) { 237207821Sjilles t = &testcases[i]; 238207821Sjilles if (strchr(t->pattern, '\'') != NULL || 239207821Sjilles strchr(t->string, '\'') != NULL) 240207821Sjilles continue; 241254231Sjilles if (t->flags == 0 && strcmp(t->pattern, "\\") == 0) 242254231Sjilles continue; 243207821Sjilles if (num == 1 && t->flags == 0) 244207821Sjilles printf("test%smatch '%s' '%s'\n", 245207821Sjilles t->result == FNM_NOMATCH ? "no" : "", 246207821Sjilles t->pattern, t->string); 247207821Sjilles if (num == 2 && (t->flags == FNM_NOESCAPE || 248207821Sjilles (t->flags == 0 && strchr(t->pattern, '\\') == NULL))) 249207821Sjilles printf("netest%smatch '%s' '%s'\n", 250207821Sjilles t->result == FNM_NOMATCH ? "no" : "", 251207821Sjilles t->pattern, t->string); 252207821Sjilles } 253207821Sjilles printf("[ -z \"$failures\" ]\n"); 254207821Sjilles return 0; 255207821Sjilles} 256207821Sjilles 257206710Sjillesint 258206710Sjillesmain(int argc, char *argv[]) 259206710Sjilles{ 260206710Sjilles size_t i, n; 261207821Sjilles int opt, flags, result, extra, errors; 262206710Sjilles struct testcase *t; 263206710Sjilles 264207821Sjilles while ((opt = getopt(argc, argv, "s:")) != -1) { 265207821Sjilles switch (opt) { 266207821Sjilles case 's': 267207821Sjilles return (write_sh_tests(argv[0], atoi(optarg))); 268207821Sjilles default: 269207821Sjilles fprintf(stderr, "usage: %s [-s num]\n", argv[0]); 270207821Sjilles fprintf(stderr, "-s option writes tests for sh(1), num is 1 or 2\n"); 271207821Sjilles exit(1); 272207821Sjilles } 273207821Sjilles } 274206710Sjilles n = sizeof(testcases) / sizeof(testcases[0]); 275206710Sjilles errors = 0; 276206710Sjilles printf("1..%zu\n", n); 277206710Sjilles for (i = 0; i < n; i++) { 278206710Sjilles t = &testcases[i]; 279206710Sjilles flags = t->flags; 280206710Sjilles extra = 0; 281206710Sjilles do { 282206710Sjilles result = fnmatch(t->pattern, t->string, flags); 283206710Sjilles if (result != t->result) 284206710Sjilles break; 285206710Sjilles if (strchr(t->pattern, '\\') == NULL && 286206710Sjilles !(flags & FNM_NOESCAPE)) { 287206710Sjilles flags |= FNM_NOESCAPE; 288206710Sjilles result = fnmatch(t->pattern, t->string, flags); 289206710Sjilles if (result != t->result) 290206710Sjilles break; 291206710Sjilles flags = t->flags; 292206710Sjilles extra++; 293206710Sjilles } 294206710Sjilles if (strchr(t->pattern, '\\') != NULL && 295206710Sjilles strchr(t->string, '\\') == NULL && 296206710Sjilles t->result == FNM_NOMATCH && 297206710Sjilles !(flags & (FNM_NOESCAPE | FNM_LEADING_DIR))) { 298206710Sjilles flags |= FNM_NOESCAPE; 299206710Sjilles result = fnmatch(t->pattern, t->string, flags); 300206710Sjilles if (result != t->result) 301206710Sjilles break; 302206710Sjilles flags = t->flags; 303206710Sjilles extra++; 304206710Sjilles } 305206710Sjilles if ((t->string[0] != '.' || t->pattern[0] == '.' || 306206710Sjilles t->result == FNM_NOMATCH) && 307206710Sjilles !(flags & (FNM_PATHNAME | FNM_PERIOD))) { 308206710Sjilles flags |= FNM_PERIOD; 309206710Sjilles result = fnmatch(t->pattern, t->string, flags); 310206710Sjilles if (result != t->result) 311206710Sjilles break; 312206710Sjilles flags = t->flags; 313206710Sjilles extra++; 314206710Sjilles } 315206710Sjilles if ((strchr(t->string, '/') == NULL || 316206710Sjilles t->result == FNM_NOMATCH) && 317206710Sjilles !(flags & FNM_PATHNAME)) { 318206710Sjilles flags |= FNM_PATHNAME; 319206710Sjilles result = fnmatch(t->pattern, t->string, flags); 320206710Sjilles if (result != t->result) 321206710Sjilles break; 322206710Sjilles flags = t->flags; 323206710Sjilles extra++; 324206710Sjilles } 325206710Sjilles if ((((t->string[0] != '.' || t->pattern[0] == '.') && 326206710Sjilles strstr(t->string, "/.") == NULL) || 327206710Sjilles t->result == FNM_NOMATCH) && 328206710Sjilles flags & FNM_PATHNAME && !(flags & FNM_PERIOD)) { 329206710Sjilles flags |= FNM_PERIOD; 330206710Sjilles result = fnmatch(t->pattern, t->string, flags); 331206710Sjilles if (result != t->result) 332206710Sjilles break; 333206710Sjilles flags = t->flags; 334206710Sjilles extra++; 335206710Sjilles } 336206710Sjilles if ((((t->string[0] != '.' || t->pattern[0] == '.') && 337206710Sjilles strchr(t->string, '/') == NULL) || 338206710Sjilles t->result == FNM_NOMATCH) && 339206710Sjilles !(flags & (FNM_PATHNAME | FNM_PERIOD))) { 340206710Sjilles flags |= FNM_PATHNAME | FNM_PERIOD; 341206710Sjilles result = fnmatch(t->pattern, t->string, flags); 342206710Sjilles if (result != t->result) 343206710Sjilles break; 344206710Sjilles flags = t->flags; 345206710Sjilles extra++; 346206710Sjilles } 347206710Sjilles if ((strchr(t->string, '/') == NULL || t->result == 0) 348206710Sjilles && !(flags & FNM_LEADING_DIR)) { 349206710Sjilles flags |= FNM_LEADING_DIR; 350206710Sjilles result = fnmatch(t->pattern, t->string, flags); 351206710Sjilles if (result != t->result) 352206710Sjilles break; 353206710Sjilles flags = t->flags; 354206710Sjilles extra++; 355206710Sjilles } 356206710Sjilles if (t->result == 0 && !(flags & FNM_CASEFOLD)) { 357206710Sjilles flags |= FNM_CASEFOLD; 358206710Sjilles result = fnmatch(t->pattern, t->string, flags); 359206710Sjilles if (result != t->result) 360206710Sjilles break; 361206710Sjilles flags = t->flags; 362206710Sjilles extra++; 363206710Sjilles } 364206710Sjilles if (strchr(t->pattern, '\\') == NULL && 365206710Sjilles t->result == 0 && 366206710Sjilles !(flags & (FNM_NOESCAPE | FNM_CASEFOLD))) { 367206710Sjilles flags |= FNM_NOESCAPE | FNM_CASEFOLD; 368206710Sjilles result = fnmatch(t->pattern, t->string, flags); 369206710Sjilles if (result != t->result) 370206710Sjilles break; 371206710Sjilles flags = t->flags; 372206710Sjilles extra++; 373206710Sjilles } 374206710Sjilles } while (0); 375206710Sjilles if (result == t->result) 376206710Sjilles printf("ok %zu - fnmatch(\"%s\", \"%s\", %s) = %d (+%d)\n", 377206710Sjilles i + 1, t->pattern, t->string, 378206710Sjilles flags_to_string(flags), 379206710Sjilles result, extra); 380206710Sjilles else { 381206710Sjilles printf("not ok %zu - fnmatch(\"%s\", \"%s\", %s) = %d != %d\n", 382206710Sjilles i + 1, t->pattern, t->string, 383206710Sjilles flags_to_string(flags), 384206710Sjilles result, t->result); 385206710Sjilles errors = 1; 386206710Sjilles } 387206710Sjilles } 388206710Sjilles 389206710Sjilles return (errors); 390206710Sjilles} 391