t / helper / test-regex.con commit t4030: abstract away SHA-1-specific constants (a6c5799)
   1#include "test-tool.h"
   2#include "git-compat-util.h"
   3#include "gettext.h"
   4
   5struct reg_flag {
   6        const char *name;
   7        int flag;
   8};
   9
  10static struct reg_flag reg_flags[] = {
  11        { "EXTENDED",    REG_EXTENDED   },
  12        { "NEWLINE",     REG_NEWLINE    },
  13        { "ICASE",       REG_ICASE      },
  14        { "NOTBOL",      REG_NOTBOL     },
  15#ifdef REG_STARTEND
  16        { "STARTEND",    REG_STARTEND   },
  17#endif
  18        { NULL, 0 }
  19};
  20
  21static int test_regex_bug(void)
  22{
  23        char *pat = "[^={} \t]+";
  24        char *str = "={}\nfred";
  25        regex_t r;
  26        regmatch_t m[1];
  27
  28        if (regcomp(&r, pat, REG_EXTENDED | REG_NEWLINE))
  29                die("failed regcomp() for pattern '%s'", pat);
  30        if (regexec(&r, str, 1, m, 0))
  31                die("no match of pattern '%s' to string '%s'", pat, str);
  32
  33        /* http://sourceware.org/bugzilla/show_bug.cgi?id=3957  */
  34        if (m[0].rm_so == 3) /* matches '\n' when it should not */
  35                die("regex bug confirmed: re-build git with NO_REGEX=1");
  36
  37        return 0;
  38}
  39
  40int cmd__regex(int argc, const char **argv)
  41{
  42        const char *pat;
  43        const char *str;
  44        int flags = 0;
  45        regex_t r;
  46        regmatch_t m[1];
  47
  48        if (argc == 2 && !strcmp(argv[1], "--bug"))
  49                return test_regex_bug();
  50        else if (argc < 3)
  51                usage("test-tool regex --bug\n"
  52                      "test-tool regex <pattern> <string> [<options>]");
  53
  54        argv++;
  55        pat = *argv++;
  56        str = *argv++;
  57        while (*argv) {
  58                struct reg_flag *rf;
  59                for (rf = reg_flags; rf->name; rf++)
  60                        if (!strcmp(*argv, rf->name)) {
  61                                flags |= rf->flag;
  62                                break;
  63                        }
  64                if (!rf->name)
  65                        die("do not recognize %s", *argv);
  66                argv++;
  67        }
  68        git_setup_gettext();
  69
  70        if (regcomp(&r, pat, flags))
  71                die("failed regcomp() for pattern '%s'", pat);
  72        if (regexec(&r, str, 1, m, 0))
  73                return 1;
  74
  75        return 0;
  76}