grep.con commit ref-filter: initialize eaten variable (04f6ee1)
   1#include "cache.h"
   2#include "config.h"
   3#include "grep.h"
   4#include "userdiff.h"
   5#include "xdiff-interface.h"
   6#include "diff.h"
   7#include "diffcore.h"
   8#include "commit.h"
   9#include "quote.h"
  10#include "help.h"
  11
  12static int grep_source_load(struct grep_source *gs);
  13static int grep_source_is_binary(struct grep_source *gs);
  14
  15static struct grep_opt grep_defaults;
  16
  17static const char *color_grep_slots[] = {
  18        [GREP_COLOR_CONTEXT]        = "context",
  19        [GREP_COLOR_FILENAME]       = "filename",
  20        [GREP_COLOR_FUNCTION]       = "function",
  21        [GREP_COLOR_LINENO]         = "lineNumber",
  22        [GREP_COLOR_MATCH_CONTEXT]  = "matchContext",
  23        [GREP_COLOR_MATCH_SELECTED] = "matchSelected",
  24        [GREP_COLOR_SELECTED]       = "selected",
  25        [GREP_COLOR_SEP]            = "separator",
  26};
  27
  28static void std_output(struct grep_opt *opt, const void *buf, size_t size)
  29{
  30        fwrite(buf, size, 1, stdout);
  31}
  32
  33static void color_set(char *dst, const char *color_bytes)
  34{
  35        xsnprintf(dst, COLOR_MAXLEN, "%s", color_bytes);
  36}
  37
  38/*
  39 * Initialize the grep_defaults template with hardcoded defaults.
  40 * We could let the compiler do this, but without C99 initializers
  41 * the code gets unwieldy and unreadable, so...
  42 */
  43void init_grep_defaults(void)
  44{
  45        struct grep_opt *opt = &grep_defaults;
  46        static int run_once;
  47
  48        if (run_once)
  49                return;
  50        run_once++;
  51
  52        memset(opt, 0, sizeof(*opt));
  53        opt->relative = 1;
  54        opt->pathname = 1;
  55        opt->max_depth = -1;
  56        opt->pattern_type_option = GREP_PATTERN_TYPE_UNSPECIFIED;
  57        color_set(opt->colors[GREP_COLOR_CONTEXT], "");
  58        color_set(opt->colors[GREP_COLOR_FILENAME], "");
  59        color_set(opt->colors[GREP_COLOR_FUNCTION], "");
  60        color_set(opt->colors[GREP_COLOR_LINENO], "");
  61        color_set(opt->colors[GREP_COLOR_MATCH_CONTEXT], GIT_COLOR_BOLD_RED);
  62        color_set(opt->colors[GREP_COLOR_MATCH_SELECTED], GIT_COLOR_BOLD_RED);
  63        color_set(opt->colors[GREP_COLOR_SELECTED], "");
  64        color_set(opt->colors[GREP_COLOR_SEP], GIT_COLOR_CYAN);
  65        opt->color = -1;
  66        opt->output = std_output;
  67}
  68
  69static int parse_pattern_type_arg(const char *opt, const char *arg)
  70{
  71        if (!strcmp(arg, "default"))
  72                return GREP_PATTERN_TYPE_UNSPECIFIED;
  73        else if (!strcmp(arg, "basic"))
  74                return GREP_PATTERN_TYPE_BRE;
  75        else if (!strcmp(arg, "extended"))
  76                return GREP_PATTERN_TYPE_ERE;
  77        else if (!strcmp(arg, "fixed"))
  78                return GREP_PATTERN_TYPE_FIXED;
  79        else if (!strcmp(arg, "perl"))
  80                return GREP_PATTERN_TYPE_PCRE;
  81        die("bad %s argument: %s", opt, arg);
  82}
  83
  84define_list_config_array_extra(color_grep_slots, {"match"});
  85
  86/*
  87 * Read the configuration file once and store it in
  88 * the grep_defaults template.
  89 */
  90int grep_config(const char *var, const char *value, void *cb)
  91{
  92        struct grep_opt *opt = &grep_defaults;
  93        const char *slot;
  94
  95        if (userdiff_config(var, value) < 0)
  96                return -1;
  97
  98        if (!strcmp(var, "grep.extendedregexp")) {
  99                opt->extended_regexp_option = git_config_bool(var, value);
 100                return 0;
 101        }
 102
 103        if (!strcmp(var, "grep.patterntype")) {
 104                opt->pattern_type_option = parse_pattern_type_arg(var, value);
 105                return 0;
 106        }
 107
 108        if (!strcmp(var, "grep.linenumber")) {
 109                opt->linenum = git_config_bool(var, value);
 110                return 0;
 111        }
 112
 113        if (!strcmp(var, "grep.fullname")) {
 114                opt->relative = !git_config_bool(var, value);
 115                return 0;
 116        }
 117
 118        if (!strcmp(var, "color.grep"))
 119                opt->color = git_config_colorbool(var, value);
 120        if (!strcmp(var, "color.grep.match")) {
 121                if (grep_config("color.grep.matchcontext", value, cb) < 0)
 122                        return -1;
 123                if (grep_config("color.grep.matchselected", value, cb) < 0)
 124                        return -1;
 125        } else if (skip_prefix(var, "color.grep.", &slot)) {
 126                int i = LOOKUP_CONFIG(color_grep_slots, slot);
 127                char *color;
 128
 129                if (i < 0)
 130                        return -1;
 131                color = opt->colors[i];
 132                if (!value)
 133                        return config_error_nonbool(var);
 134                return color_parse(value, color);
 135        }
 136        return 0;
 137}
 138
 139/*
 140 * Initialize one instance of grep_opt and copy the
 141 * default values from the template we read the configuration
 142 * information in an earlier call to git_config(grep_config).
 143 */
 144void grep_init(struct grep_opt *opt, const char *prefix)
 145{
 146        struct grep_opt *def = &grep_defaults;
 147        int i;
 148
 149        memset(opt, 0, sizeof(*opt));
 150        opt->prefix = prefix;
 151        opt->prefix_length = (prefix && *prefix) ? strlen(prefix) : 0;
 152        opt->pattern_tail = &opt->pattern_list;
 153        opt->header_tail = &opt->header_list;
 154
 155        opt->color = def->color;
 156        opt->extended_regexp_option = def->extended_regexp_option;
 157        opt->pattern_type_option = def->pattern_type_option;
 158        opt->linenum = def->linenum;
 159        opt->max_depth = def->max_depth;
 160        opt->pathname = def->pathname;
 161        opt->relative = def->relative;
 162        opt->output = def->output;
 163
 164        for (i = 0; i < NR_GREP_COLORS; i++)
 165                color_set(opt->colors[i], def->colors[i]);
 166}
 167
 168static void grep_set_pattern_type_option(enum grep_pattern_type pattern_type, struct grep_opt *opt)
 169{
 170        /*
 171         * When committing to the pattern type by setting the relevant
 172         * fields in grep_opt it's generally not necessary to zero out
 173         * the fields we're not choosing, since they won't have been
 174         * set by anything. The extended_regexp_option field is the
 175         * only exception to this.
 176         *
 177         * This is because in the process of parsing grep.patternType
 178         * & grep.extendedRegexp we set opt->pattern_type_option and
 179         * opt->extended_regexp_option, respectively. We then
 180         * internally use opt->extended_regexp_option to see if we're
 181         * compiling an ERE. It must be unset if that's not actually
 182         * the case.
 183         */
 184        if (pattern_type != GREP_PATTERN_TYPE_ERE &&
 185            opt->extended_regexp_option)
 186                opt->extended_regexp_option = 0;
 187
 188        switch (pattern_type) {
 189        case GREP_PATTERN_TYPE_UNSPECIFIED:
 190                /* fall through */
 191
 192        case GREP_PATTERN_TYPE_BRE:
 193                break;
 194
 195        case GREP_PATTERN_TYPE_ERE:
 196                opt->extended_regexp_option = 1;
 197                break;
 198
 199        case GREP_PATTERN_TYPE_FIXED:
 200                opt->fixed = 1;
 201                break;
 202
 203        case GREP_PATTERN_TYPE_PCRE:
 204#ifdef USE_LIBPCRE2
 205                opt->pcre2 = 1;
 206#else
 207                /*
 208                 * It's important that pcre1 always be assigned to
 209                 * even when there's no USE_LIBPCRE* defined. We still
 210                 * call the PCRE stub function, it just dies with
 211                 * "cannot use Perl-compatible regexes[...]".
 212                 */
 213                opt->pcre1 = 1;
 214#endif
 215                break;
 216        }
 217}
 218
 219void grep_commit_pattern_type(enum grep_pattern_type pattern_type, struct grep_opt *opt)
 220{
 221        if (pattern_type != GREP_PATTERN_TYPE_UNSPECIFIED)
 222                grep_set_pattern_type_option(pattern_type, opt);
 223        else if (opt->pattern_type_option != GREP_PATTERN_TYPE_UNSPECIFIED)
 224                grep_set_pattern_type_option(opt->pattern_type_option, opt);
 225        else if (opt->extended_regexp_option)
 226                /*
 227                 * This branch *must* happen after setting from the
 228                 * opt->pattern_type_option above, we don't want
 229                 * grep.extendedRegexp to override grep.patternType!
 230                 */
 231                grep_set_pattern_type_option(GREP_PATTERN_TYPE_ERE, opt);
 232}
 233
 234static struct grep_pat *create_grep_pat(const char *pat, size_t patlen,
 235                                        const char *origin, int no,
 236                                        enum grep_pat_token t,
 237                                        enum grep_header_field field)
 238{
 239        struct grep_pat *p = xcalloc(1, sizeof(*p));
 240        p->pattern = xmemdupz(pat, patlen);
 241        p->patternlen = patlen;
 242        p->origin = origin;
 243        p->no = no;
 244        p->token = t;
 245        p->field = field;
 246        return p;
 247}
 248
 249static void do_append_grep_pat(struct grep_pat ***tail, struct grep_pat *p)
 250{
 251        **tail = p;
 252        *tail = &p->next;
 253        p->next = NULL;
 254
 255        switch (p->token) {
 256        case GREP_PATTERN: /* atom */
 257        case GREP_PATTERN_HEAD:
 258        case GREP_PATTERN_BODY:
 259                for (;;) {
 260                        struct grep_pat *new_pat;
 261                        size_t len = 0;
 262                        char *cp = p->pattern + p->patternlen, *nl = NULL;
 263                        while (++len <= p->patternlen) {
 264                                if (*(--cp) == '\n') {
 265                                        nl = cp;
 266                                        break;
 267                                }
 268                        }
 269                        if (!nl)
 270                                break;
 271                        new_pat = create_grep_pat(nl + 1, len - 1, p->origin,
 272                                                  p->no, p->token, p->field);
 273                        new_pat->next = p->next;
 274                        if (!p->next)
 275                                *tail = &new_pat->next;
 276                        p->next = new_pat;
 277                        *nl = '\0';
 278                        p->patternlen -= len;
 279                }
 280                break;
 281        default:
 282                break;
 283        }
 284}
 285
 286void append_header_grep_pattern(struct grep_opt *opt,
 287                                enum grep_header_field field, const char *pat)
 288{
 289        struct grep_pat *p = create_grep_pat(pat, strlen(pat), "header", 0,
 290                                             GREP_PATTERN_HEAD, field);
 291        if (field == GREP_HEADER_REFLOG)
 292                opt->use_reflog_filter = 1;
 293        do_append_grep_pat(&opt->header_tail, p);
 294}
 295
 296void append_grep_pattern(struct grep_opt *opt, const char *pat,
 297                         const char *origin, int no, enum grep_pat_token t)
 298{
 299        append_grep_pat(opt, pat, strlen(pat), origin, no, t);
 300}
 301
 302void append_grep_pat(struct grep_opt *opt, const char *pat, size_t patlen,
 303                     const char *origin, int no, enum grep_pat_token t)
 304{
 305        struct grep_pat *p = create_grep_pat(pat, patlen, origin, no, t, 0);
 306        do_append_grep_pat(&opt->pattern_tail, p);
 307}
 308
 309struct grep_opt *grep_opt_dup(const struct grep_opt *opt)
 310{
 311        struct grep_pat *pat;
 312        struct grep_opt *ret = xmalloc(sizeof(struct grep_opt));
 313        *ret = *opt;
 314
 315        ret->pattern_list = NULL;
 316        ret->pattern_tail = &ret->pattern_list;
 317
 318        for(pat = opt->pattern_list; pat != NULL; pat = pat->next)
 319        {
 320                if(pat->token == GREP_PATTERN_HEAD)
 321                        append_header_grep_pattern(ret, pat->field,
 322                                                   pat->pattern);
 323                else
 324                        append_grep_pat(ret, pat->pattern, pat->patternlen,
 325                                        pat->origin, pat->no, pat->token);
 326        }
 327
 328        return ret;
 329}
 330
 331static NORETURN void compile_regexp_failed(const struct grep_pat *p,
 332                const char *error)
 333{
 334        char where[1024];
 335
 336        if (p->no)
 337                xsnprintf(where, sizeof(where), "In '%s' at %d, ", p->origin, p->no);
 338        else if (p->origin)
 339                xsnprintf(where, sizeof(where), "%s, ", p->origin);
 340        else
 341                where[0] = 0;
 342
 343        die("%s'%s': %s", where, p->pattern, error);
 344}
 345
 346static int is_fixed(const char *s, size_t len)
 347{
 348        size_t i;
 349
 350        for (i = 0; i < len; i++) {
 351                if (is_regex_special(s[i]))
 352                        return 0;
 353        }
 354
 355        return 1;
 356}
 357
 358static int has_null(const char *s, size_t len)
 359{
 360        /*
 361         * regcomp cannot accept patterns with NULs so when using it
 362         * we consider any pattern containing a NUL fixed.
 363         */
 364        if (memchr(s, 0, len))
 365                return 1;
 366
 367        return 0;
 368}
 369
 370#ifdef USE_LIBPCRE1
 371static void compile_pcre1_regexp(struct grep_pat *p, const struct grep_opt *opt)
 372{
 373        const char *error;
 374        int erroffset;
 375        int options = PCRE_MULTILINE;
 376
 377        if (opt->ignore_case) {
 378                if (has_non_ascii(p->pattern))
 379                        p->pcre1_tables = pcre_maketables();
 380                options |= PCRE_CASELESS;
 381        }
 382        if (is_utf8_locale() && has_non_ascii(p->pattern))
 383                options |= PCRE_UTF8;
 384
 385        p->pcre1_regexp = pcre_compile(p->pattern, options, &error, &erroffset,
 386                                      p->pcre1_tables);
 387        if (!p->pcre1_regexp)
 388                compile_regexp_failed(p, error);
 389
 390        p->pcre1_extra_info = pcre_study(p->pcre1_regexp, GIT_PCRE_STUDY_JIT_COMPILE, &error);
 391        if (!p->pcre1_extra_info && error)
 392                die("%s", error);
 393
 394#ifdef GIT_PCRE1_USE_JIT
 395        pcre_config(PCRE_CONFIG_JIT, &p->pcre1_jit_on);
 396        if (p->pcre1_jit_on == 1) {
 397                p->pcre1_jit_stack = pcre_jit_stack_alloc(1, 1024 * 1024);
 398                if (!p->pcre1_jit_stack)
 399                        die("Couldn't allocate PCRE JIT stack");
 400                pcre_assign_jit_stack(p->pcre1_extra_info, NULL, p->pcre1_jit_stack);
 401        } else if (p->pcre1_jit_on != 0) {
 402                BUG("The pcre1_jit_on variable should be 0 or 1, not %d",
 403                    p->pcre1_jit_on);
 404        }
 405#endif
 406}
 407
 408static int pcre1match(struct grep_pat *p, const char *line, const char *eol,
 409                regmatch_t *match, int eflags)
 410{
 411        int ovector[30], ret, flags = 0;
 412
 413        if (eflags & REG_NOTBOL)
 414                flags |= PCRE_NOTBOL;
 415
 416#ifdef GIT_PCRE1_USE_JIT
 417        if (p->pcre1_jit_on) {
 418                ret = pcre_jit_exec(p->pcre1_regexp, p->pcre1_extra_info, line,
 419                                    eol - line, 0, flags, ovector,
 420                                    ARRAY_SIZE(ovector), p->pcre1_jit_stack);
 421        } else
 422#endif
 423        {
 424                ret = pcre_exec(p->pcre1_regexp, p->pcre1_extra_info, line,
 425                                eol - line, 0, flags, ovector,
 426                                ARRAY_SIZE(ovector));
 427        }
 428
 429        if (ret < 0 && ret != PCRE_ERROR_NOMATCH)
 430                die("pcre_exec failed with error code %d", ret);
 431        if (ret > 0) {
 432                ret = 0;
 433                match->rm_so = ovector[0];
 434                match->rm_eo = ovector[1];
 435        }
 436
 437        return ret;
 438}
 439
 440static void free_pcre1_regexp(struct grep_pat *p)
 441{
 442        pcre_free(p->pcre1_regexp);
 443#ifdef GIT_PCRE1_USE_JIT
 444        if (p->pcre1_jit_on) {
 445                pcre_free_study(p->pcre1_extra_info);
 446                pcre_jit_stack_free(p->pcre1_jit_stack);
 447        } else
 448#endif
 449        {
 450                pcre_free(p->pcre1_extra_info);
 451        }
 452        pcre_free((void *)p->pcre1_tables);
 453}
 454#else /* !USE_LIBPCRE1 */
 455static void compile_pcre1_regexp(struct grep_pat *p, const struct grep_opt *opt)
 456{
 457        die("cannot use Perl-compatible regexes when not compiled with USE_LIBPCRE");
 458}
 459
 460static int pcre1match(struct grep_pat *p, const char *line, const char *eol,
 461                regmatch_t *match, int eflags)
 462{
 463        return 1;
 464}
 465
 466static void free_pcre1_regexp(struct grep_pat *p)
 467{
 468}
 469#endif /* !USE_LIBPCRE1 */
 470
 471#ifdef USE_LIBPCRE2
 472static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt)
 473{
 474        int error;
 475        PCRE2_UCHAR errbuf[256];
 476        PCRE2_SIZE erroffset;
 477        int options = PCRE2_MULTILINE;
 478        const uint8_t *character_tables = NULL;
 479        int jitret;
 480        int patinforet;
 481        size_t jitsizearg;
 482
 483        assert(opt->pcre2);
 484
 485        p->pcre2_compile_context = NULL;
 486
 487        if (opt->ignore_case) {
 488                if (has_non_ascii(p->pattern)) {
 489                        character_tables = pcre2_maketables(NULL);
 490                        p->pcre2_compile_context = pcre2_compile_context_create(NULL);
 491                        pcre2_set_character_tables(p->pcre2_compile_context, character_tables);
 492                }
 493                options |= PCRE2_CASELESS;
 494        }
 495        if (is_utf8_locale() && has_non_ascii(p->pattern))
 496                options |= PCRE2_UTF;
 497
 498        p->pcre2_pattern = pcre2_compile((PCRE2_SPTR)p->pattern,
 499                                         p->patternlen, options, &error, &erroffset,
 500                                         p->pcre2_compile_context);
 501
 502        if (p->pcre2_pattern) {
 503                p->pcre2_match_data = pcre2_match_data_create_from_pattern(p->pcre2_pattern, NULL);
 504                if (!p->pcre2_match_data)
 505                        die("Couldn't allocate PCRE2 match data");
 506        } else {
 507                pcre2_get_error_message(error, errbuf, sizeof(errbuf));
 508                compile_regexp_failed(p, (const char *)&errbuf);
 509        }
 510
 511        pcre2_config(PCRE2_CONFIG_JIT, &p->pcre2_jit_on);
 512        if (p->pcre2_jit_on == 1) {
 513                jitret = pcre2_jit_compile(p->pcre2_pattern, PCRE2_JIT_COMPLETE);
 514                if (jitret)
 515                        die("Couldn't JIT the PCRE2 pattern '%s', got '%d'\n", p->pattern, jitret);
 516
 517                /*
 518                 * The pcre2_config(PCRE2_CONFIG_JIT, ...) call just
 519                 * tells us whether the library itself supports JIT,
 520                 * but to see whether we're going to be actually using
 521                 * JIT we need to extract PCRE2_INFO_JITSIZE from the
 522                 * pattern *after* we do pcre2_jit_compile() above.
 523                 *
 524                 * This is because if the pattern contains the
 525                 * (*NO_JIT) verb (see pcre2syntax(3))
 526                 * pcre2_jit_compile() will exit early with 0. If we
 527                 * then proceed to call pcre2_jit_match() further down
 528                 * the line instead of pcre2_match() we'll either
 529                 * segfault (pre PCRE 10.31) or run into a fatal error
 530                 * (post PCRE2 10.31)
 531                 */
 532                patinforet = pcre2_pattern_info(p->pcre2_pattern, PCRE2_INFO_JITSIZE, &jitsizearg);
 533                if (patinforet)
 534                        BUG("pcre2_pattern_info() failed: %d", patinforet);
 535                if (jitsizearg == 0) {
 536                        p->pcre2_jit_on = 0;
 537                        return;
 538                }
 539
 540                p->pcre2_jit_stack = pcre2_jit_stack_create(1, 1024 * 1024, NULL);
 541                if (!p->pcre2_jit_stack)
 542                        die("Couldn't allocate PCRE2 JIT stack");
 543                p->pcre2_match_context = pcre2_match_context_create(NULL);
 544                if (!p->pcre2_match_context)
 545                        die("Couldn't allocate PCRE2 match context");
 546                pcre2_jit_stack_assign(p->pcre2_match_context, NULL, p->pcre2_jit_stack);
 547        } else if (p->pcre2_jit_on != 0) {
 548                BUG("The pcre2_jit_on variable should be 0 or 1, not %d",
 549                    p->pcre1_jit_on);
 550        }
 551}
 552
 553static int pcre2match(struct grep_pat *p, const char *line, const char *eol,
 554                regmatch_t *match, int eflags)
 555{
 556        int ret, flags = 0;
 557        PCRE2_SIZE *ovector;
 558        PCRE2_UCHAR errbuf[256];
 559
 560        if (eflags & REG_NOTBOL)
 561                flags |= PCRE2_NOTBOL;
 562
 563        if (p->pcre2_jit_on)
 564                ret = pcre2_jit_match(p->pcre2_pattern, (unsigned char *)line,
 565                                      eol - line, 0, flags, p->pcre2_match_data,
 566                                      NULL);
 567        else
 568                ret = pcre2_match(p->pcre2_pattern, (unsigned char *)line,
 569                                  eol - line, 0, flags, p->pcre2_match_data,
 570                                  NULL);
 571
 572        if (ret < 0 && ret != PCRE2_ERROR_NOMATCH) {
 573                pcre2_get_error_message(ret, errbuf, sizeof(errbuf));
 574                die("%s failed with error code %d: %s",
 575                    (p->pcre2_jit_on ? "pcre2_jit_match" : "pcre2_match"), ret,
 576                    errbuf);
 577        }
 578        if (ret > 0) {
 579                ovector = pcre2_get_ovector_pointer(p->pcre2_match_data);
 580                ret = 0;
 581                match->rm_so = (int)ovector[0];
 582                match->rm_eo = (int)ovector[1];
 583        }
 584
 585        return ret;
 586}
 587
 588static void free_pcre2_pattern(struct grep_pat *p)
 589{
 590        pcre2_compile_context_free(p->pcre2_compile_context);
 591        pcre2_code_free(p->pcre2_pattern);
 592        pcre2_match_data_free(p->pcre2_match_data);
 593        pcre2_jit_stack_free(p->pcre2_jit_stack);
 594        pcre2_match_context_free(p->pcre2_match_context);
 595}
 596#else /* !USE_LIBPCRE2 */
 597static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt)
 598{
 599        /*
 600         * Unreachable until USE_LIBPCRE2 becomes synonymous with
 601         * USE_LIBPCRE. See the sibling comment in
 602         * grep_set_pattern_type_option().
 603         */
 604        die("cannot use Perl-compatible regexes when not compiled with USE_LIBPCRE");
 605}
 606
 607static int pcre2match(struct grep_pat *p, const char *line, const char *eol,
 608                regmatch_t *match, int eflags)
 609{
 610        return 1;
 611}
 612
 613static void free_pcre2_pattern(struct grep_pat *p)
 614{
 615}
 616#endif /* !USE_LIBPCRE2 */
 617
 618static void compile_fixed_regexp(struct grep_pat *p, struct grep_opt *opt)
 619{
 620        struct strbuf sb = STRBUF_INIT;
 621        int err;
 622        int regflags = 0;
 623
 624        basic_regex_quote_buf(&sb, p->pattern);
 625        if (opt->ignore_case)
 626                regflags |= REG_ICASE;
 627        err = regcomp(&p->regexp, sb.buf, regflags);
 628        if (opt->debug)
 629                fprintf(stderr, "fixed %s\n", sb.buf);
 630        strbuf_release(&sb);
 631        if (err) {
 632                char errbuf[1024];
 633                regerror(err, &p->regexp, errbuf, sizeof(errbuf));
 634                compile_regexp_failed(p, errbuf);
 635        }
 636}
 637
 638static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
 639{
 640        int ascii_only;
 641        int err;
 642        int regflags = REG_NEWLINE;
 643
 644        p->word_regexp = opt->word_regexp;
 645        p->ignore_case = opt->ignore_case;
 646        ascii_only     = !has_non_ascii(p->pattern);
 647
 648        /*
 649         * Even when -F (fixed) asks us to do a non-regexp search, we
 650         * may not be able to correctly case-fold when -i
 651         * (ignore-case) is asked (in which case, we'll synthesize a
 652         * regexp to match the pattern that matches regexp special
 653         * characters literally, while ignoring case differences).  On
 654         * the other hand, even without -F, if the pattern does not
 655         * have any regexp special characters and there is no need for
 656         * case-folding search, we can internally turn it into a
 657         * simple string match using kws.  p->fixed tells us if we
 658         * want to use kws.
 659         */
 660        if (opt->fixed ||
 661            has_null(p->pattern, p->patternlen) ||
 662            is_fixed(p->pattern, p->patternlen))
 663                p->fixed = !p->ignore_case || ascii_only;
 664
 665        if (p->fixed) {
 666                p->kws = kwsalloc(p->ignore_case ? tolower_trans_tbl : NULL);
 667                kwsincr(p->kws, p->pattern, p->patternlen);
 668                kwsprep(p->kws);
 669                return;
 670        } else if (opt->fixed) {
 671                /*
 672                 * We come here when the pattern has the non-ascii
 673                 * characters we cannot case-fold, and asked to
 674                 * ignore-case.
 675                 */
 676                compile_fixed_regexp(p, opt);
 677                return;
 678        }
 679
 680        if (opt->pcre2) {
 681                compile_pcre2_pattern(p, opt);
 682                return;
 683        }
 684
 685        if (opt->pcre1) {
 686                compile_pcre1_regexp(p, opt);
 687                return;
 688        }
 689
 690        if (p->ignore_case)
 691                regflags |= REG_ICASE;
 692        if (opt->extended_regexp_option)
 693                regflags |= REG_EXTENDED;
 694        err = regcomp(&p->regexp, p->pattern, regflags);
 695        if (err) {
 696                char errbuf[1024];
 697                regerror(err, &p->regexp, errbuf, 1024);
 698                compile_regexp_failed(p, errbuf);
 699        }
 700}
 701
 702static struct grep_expr *compile_pattern_or(struct grep_pat **);
 703static struct grep_expr *compile_pattern_atom(struct grep_pat **list)
 704{
 705        struct grep_pat *p;
 706        struct grep_expr *x;
 707
 708        p = *list;
 709        if (!p)
 710                return NULL;
 711        switch (p->token) {
 712        case GREP_PATTERN: /* atom */
 713        case GREP_PATTERN_HEAD:
 714        case GREP_PATTERN_BODY:
 715                x = xcalloc(1, sizeof (struct grep_expr));
 716                x->node = GREP_NODE_ATOM;
 717                x->u.atom = p;
 718                *list = p->next;
 719                return x;
 720        case GREP_OPEN_PAREN:
 721                *list = p->next;
 722                x = compile_pattern_or(list);
 723                if (!*list || (*list)->token != GREP_CLOSE_PAREN)
 724                        die("unmatched parenthesis");
 725                *list = (*list)->next;
 726                return x;
 727        default:
 728                return NULL;
 729        }
 730}
 731
 732static struct grep_expr *compile_pattern_not(struct grep_pat **list)
 733{
 734        struct grep_pat *p;
 735        struct grep_expr *x;
 736
 737        p = *list;
 738        if (!p)
 739                return NULL;
 740        switch (p->token) {
 741        case GREP_NOT:
 742                if (!p->next)
 743                        die("--not not followed by pattern expression");
 744                *list = p->next;
 745                x = xcalloc(1, sizeof (struct grep_expr));
 746                x->node = GREP_NODE_NOT;
 747                x->u.unary = compile_pattern_not(list);
 748                if (!x->u.unary)
 749                        die("--not followed by non pattern expression");
 750                return x;
 751        default:
 752                return compile_pattern_atom(list);
 753        }
 754}
 755
 756static struct grep_expr *compile_pattern_and(struct grep_pat **list)
 757{
 758        struct grep_pat *p;
 759        struct grep_expr *x, *y, *z;
 760
 761        x = compile_pattern_not(list);
 762        p = *list;
 763        if (p && p->token == GREP_AND) {
 764                if (!p->next)
 765                        die("--and not followed by pattern expression");
 766                *list = p->next;
 767                y = compile_pattern_and(list);
 768                if (!y)
 769                        die("--and not followed by pattern expression");
 770                z = xcalloc(1, sizeof (struct grep_expr));
 771                z->node = GREP_NODE_AND;
 772                z->u.binary.left = x;
 773                z->u.binary.right = y;
 774                return z;
 775        }
 776        return x;
 777}
 778
 779static struct grep_expr *compile_pattern_or(struct grep_pat **list)
 780{
 781        struct grep_pat *p;
 782        struct grep_expr *x, *y, *z;
 783
 784        x = compile_pattern_and(list);
 785        p = *list;
 786        if (x && p && p->token != GREP_CLOSE_PAREN) {
 787                y = compile_pattern_or(list);
 788                if (!y)
 789                        die("not a pattern expression %s", p->pattern);
 790                z = xcalloc(1, sizeof (struct grep_expr));
 791                z->node = GREP_NODE_OR;
 792                z->u.binary.left = x;
 793                z->u.binary.right = y;
 794                return z;
 795        }
 796        return x;
 797}
 798
 799static struct grep_expr *compile_pattern_expr(struct grep_pat **list)
 800{
 801        return compile_pattern_or(list);
 802}
 803
 804static void indent(int in)
 805{
 806        while (in-- > 0)
 807                fputc(' ', stderr);
 808}
 809
 810static void dump_grep_pat(struct grep_pat *p)
 811{
 812        switch (p->token) {
 813        case GREP_AND: fprintf(stderr, "*and*"); break;
 814        case GREP_OPEN_PAREN: fprintf(stderr, "*(*"); break;
 815        case GREP_CLOSE_PAREN: fprintf(stderr, "*)*"); break;
 816        case GREP_NOT: fprintf(stderr, "*not*"); break;
 817        case GREP_OR: fprintf(stderr, "*or*"); break;
 818
 819        case GREP_PATTERN: fprintf(stderr, "pattern"); break;
 820        case GREP_PATTERN_HEAD: fprintf(stderr, "pattern_head"); break;
 821        case GREP_PATTERN_BODY: fprintf(stderr, "pattern_body"); break;
 822        }
 823
 824        switch (p->token) {
 825        default: break;
 826        case GREP_PATTERN_HEAD:
 827                fprintf(stderr, "<head %d>", p->field); break;
 828        case GREP_PATTERN_BODY:
 829                fprintf(stderr, "<body>"); break;
 830        }
 831        switch (p->token) {
 832        default: break;
 833        case GREP_PATTERN_HEAD:
 834        case GREP_PATTERN_BODY:
 835        case GREP_PATTERN:
 836                fprintf(stderr, "%.*s", (int)p->patternlen, p->pattern);
 837                break;
 838        }
 839        fputc('\n', stderr);
 840}
 841
 842static void dump_grep_expression_1(struct grep_expr *x, int in)
 843{
 844        indent(in);
 845        switch (x->node) {
 846        case GREP_NODE_TRUE:
 847                fprintf(stderr, "true\n");
 848                break;
 849        case GREP_NODE_ATOM:
 850                dump_grep_pat(x->u.atom);
 851                break;
 852        case GREP_NODE_NOT:
 853                fprintf(stderr, "(not\n");
 854                dump_grep_expression_1(x->u.unary, in+1);
 855                indent(in);
 856                fprintf(stderr, ")\n");
 857                break;
 858        case GREP_NODE_AND:
 859                fprintf(stderr, "(and\n");
 860                dump_grep_expression_1(x->u.binary.left, in+1);
 861                dump_grep_expression_1(x->u.binary.right, in+1);
 862                indent(in);
 863                fprintf(stderr, ")\n");
 864                break;
 865        case GREP_NODE_OR:
 866                fprintf(stderr, "(or\n");
 867                dump_grep_expression_1(x->u.binary.left, in+1);
 868                dump_grep_expression_1(x->u.binary.right, in+1);
 869                indent(in);
 870                fprintf(stderr, ")\n");
 871                break;
 872        }
 873}
 874
 875static void dump_grep_expression(struct grep_opt *opt)
 876{
 877        struct grep_expr *x = opt->pattern_expression;
 878
 879        if (opt->all_match)
 880                fprintf(stderr, "[all-match]\n");
 881        dump_grep_expression_1(x, 0);
 882        fflush(NULL);
 883}
 884
 885static struct grep_expr *grep_true_expr(void)
 886{
 887        struct grep_expr *z = xcalloc(1, sizeof(*z));
 888        z->node = GREP_NODE_TRUE;
 889        return z;
 890}
 891
 892static struct grep_expr *grep_or_expr(struct grep_expr *left, struct grep_expr *right)
 893{
 894        struct grep_expr *z = xcalloc(1, sizeof(*z));
 895        z->node = GREP_NODE_OR;
 896        z->u.binary.left = left;
 897        z->u.binary.right = right;
 898        return z;
 899}
 900
 901static struct grep_expr *prep_header_patterns(struct grep_opt *opt)
 902{
 903        struct grep_pat *p;
 904        struct grep_expr *header_expr;
 905        struct grep_expr *(header_group[GREP_HEADER_FIELD_MAX]);
 906        enum grep_header_field fld;
 907
 908        if (!opt->header_list)
 909                return NULL;
 910
 911        for (p = opt->header_list; p; p = p->next) {
 912                if (p->token != GREP_PATTERN_HEAD)
 913                        BUG("a non-header pattern in grep header list.");
 914                if (p->field < GREP_HEADER_FIELD_MIN ||
 915                    GREP_HEADER_FIELD_MAX <= p->field)
 916                        BUG("unknown header field %d", p->field);
 917                compile_regexp(p, opt);
 918        }
 919
 920        for (fld = 0; fld < GREP_HEADER_FIELD_MAX; fld++)
 921                header_group[fld] = NULL;
 922
 923        for (p = opt->header_list; p; p = p->next) {
 924                struct grep_expr *h;
 925                struct grep_pat *pp = p;
 926
 927                h = compile_pattern_atom(&pp);
 928                if (!h || pp != p->next)
 929                        BUG("malformed header expr");
 930                if (!header_group[p->field]) {
 931                        header_group[p->field] = h;
 932                        continue;
 933                }
 934                header_group[p->field] = grep_or_expr(h, header_group[p->field]);
 935        }
 936
 937        header_expr = NULL;
 938
 939        for (fld = 0; fld < GREP_HEADER_FIELD_MAX; fld++) {
 940                if (!header_group[fld])
 941                        continue;
 942                if (!header_expr)
 943                        header_expr = grep_true_expr();
 944                header_expr = grep_or_expr(header_group[fld], header_expr);
 945        }
 946        return header_expr;
 947}
 948
 949static struct grep_expr *grep_splice_or(struct grep_expr *x, struct grep_expr *y)
 950{
 951        struct grep_expr *z = x;
 952
 953        while (x) {
 954                assert(x->node == GREP_NODE_OR);
 955                if (x->u.binary.right &&
 956                    x->u.binary.right->node == GREP_NODE_TRUE) {
 957                        x->u.binary.right = y;
 958                        break;
 959                }
 960                x = x->u.binary.right;
 961        }
 962        return z;
 963}
 964
 965static void compile_grep_patterns_real(struct grep_opt *opt)
 966{
 967        struct grep_pat *p;
 968        struct grep_expr *header_expr = prep_header_patterns(opt);
 969
 970        for (p = opt->pattern_list; p; p = p->next) {
 971                switch (p->token) {
 972                case GREP_PATTERN: /* atom */
 973                case GREP_PATTERN_HEAD:
 974                case GREP_PATTERN_BODY:
 975                        compile_regexp(p, opt);
 976                        break;
 977                default:
 978                        opt->extended = 1;
 979                        break;
 980                }
 981        }
 982
 983        if (opt->all_match || header_expr)
 984                opt->extended = 1;
 985        else if (!opt->extended && !opt->debug)
 986                return;
 987
 988        p = opt->pattern_list;
 989        if (p)
 990                opt->pattern_expression = compile_pattern_expr(&p);
 991        if (p)
 992                die("incomplete pattern expression: %s", p->pattern);
 993
 994        if (!header_expr)
 995                return;
 996
 997        if (!opt->pattern_expression)
 998                opt->pattern_expression = header_expr;
 999        else if (opt->all_match)
1000                opt->pattern_expression = grep_splice_or(header_expr,
1001                                                         opt->pattern_expression);
1002        else
1003                opt->pattern_expression = grep_or_expr(opt->pattern_expression,
1004                                                       header_expr);
1005        opt->all_match = 1;
1006}
1007
1008void compile_grep_patterns(struct grep_opt *opt)
1009{
1010        compile_grep_patterns_real(opt);
1011        if (opt->debug)
1012                dump_grep_expression(opt);
1013}
1014
1015static void free_pattern_expr(struct grep_expr *x)
1016{
1017        switch (x->node) {
1018        case GREP_NODE_TRUE:
1019        case GREP_NODE_ATOM:
1020                break;
1021        case GREP_NODE_NOT:
1022                free_pattern_expr(x->u.unary);
1023                break;
1024        case GREP_NODE_AND:
1025        case GREP_NODE_OR:
1026                free_pattern_expr(x->u.binary.left);
1027                free_pattern_expr(x->u.binary.right);
1028                break;
1029        }
1030        free(x);
1031}
1032
1033void free_grep_patterns(struct grep_opt *opt)
1034{
1035        struct grep_pat *p, *n;
1036
1037        for (p = opt->pattern_list; p; p = n) {
1038                n = p->next;
1039                switch (p->token) {
1040                case GREP_PATTERN: /* atom */
1041                case GREP_PATTERN_HEAD:
1042                case GREP_PATTERN_BODY:
1043                        if (p->kws)
1044                                kwsfree(p->kws);
1045                        else if (p->pcre1_regexp)
1046                                free_pcre1_regexp(p);
1047                        else if (p->pcre2_pattern)
1048                                free_pcre2_pattern(p);
1049                        else
1050                                regfree(&p->regexp);
1051                        free(p->pattern);
1052                        break;
1053                default:
1054                        break;
1055                }
1056                free(p);
1057        }
1058
1059        if (!opt->extended)
1060                return;
1061        free_pattern_expr(opt->pattern_expression);
1062}
1063
1064static char *end_of_line(char *cp, unsigned long *left)
1065{
1066        unsigned long l = *left;
1067        while (l && *cp != '\n') {
1068                l--;
1069                cp++;
1070        }
1071        *left = l;
1072        return cp;
1073}
1074
1075static int word_char(char ch)
1076{
1077        return isalnum(ch) || ch == '_';
1078}
1079
1080static void output_color(struct grep_opt *opt, const void *data, size_t size,
1081                         const char *color)
1082{
1083        if (want_color(opt->color) && color && color[0]) {
1084                opt->output(opt, color, strlen(color));
1085                opt->output(opt, data, size);
1086                opt->output(opt, GIT_COLOR_RESET, strlen(GIT_COLOR_RESET));
1087        } else
1088                opt->output(opt, data, size);
1089}
1090
1091static void output_sep(struct grep_opt *opt, char sign)
1092{
1093        if (opt->null_following_name)
1094                opt->output(opt, "\0", 1);
1095        else
1096                output_color(opt, &sign, 1, opt->colors[GREP_COLOR_SEP]);
1097}
1098
1099static void show_name(struct grep_opt *opt, const char *name)
1100{
1101        output_color(opt, name, strlen(name), opt->colors[GREP_COLOR_FILENAME]);
1102        opt->output(opt, opt->null_following_name ? "\0" : "\n", 1);
1103}
1104
1105static int fixmatch(struct grep_pat *p, char *line, char *eol,
1106                    regmatch_t *match)
1107{
1108        struct kwsmatch kwsm;
1109        size_t offset = kwsexec(p->kws, line, eol - line, &kwsm);
1110        if (offset == -1) {
1111                match->rm_so = match->rm_eo = -1;
1112                return REG_NOMATCH;
1113        } else {
1114                match->rm_so = offset;
1115                match->rm_eo = match->rm_so + kwsm.size[0];
1116                return 0;
1117        }
1118}
1119
1120static int patmatch(struct grep_pat *p, char *line, char *eol,
1121                    regmatch_t *match, int eflags)
1122{
1123        int hit;
1124
1125        if (p->fixed)
1126                hit = !fixmatch(p, line, eol, match);
1127        else if (p->pcre1_regexp)
1128                hit = !pcre1match(p, line, eol, match, eflags);
1129        else if (p->pcre2_pattern)
1130                hit = !pcre2match(p, line, eol, match, eflags);
1131        else
1132                hit = !regexec_buf(&p->regexp, line, eol - line, 1, match,
1133                                   eflags);
1134
1135        return hit;
1136}
1137
1138static int strip_timestamp(char *bol, char **eol_p)
1139{
1140        char *eol = *eol_p;
1141        int ch;
1142
1143        while (bol < --eol) {
1144                if (*eol != '>')
1145                        continue;
1146                *eol_p = ++eol;
1147                ch = *eol;
1148                *eol = '\0';
1149                return ch;
1150        }
1151        return 0;
1152}
1153
1154static struct {
1155        const char *field;
1156        size_t len;
1157} header_field[] = {
1158        { "author ", 7 },
1159        { "committer ", 10 },
1160        { "reflog ", 7 },
1161};
1162
1163static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
1164                             enum grep_context ctx,
1165                             regmatch_t *pmatch, int eflags)
1166{
1167        int hit = 0;
1168        int saved_ch = 0;
1169        const char *start = bol;
1170
1171        if ((p->token != GREP_PATTERN) &&
1172            ((p->token == GREP_PATTERN_HEAD) != (ctx == GREP_CONTEXT_HEAD)))
1173                return 0;
1174
1175        if (p->token == GREP_PATTERN_HEAD) {
1176                const char *field;
1177                size_t len;
1178                assert(p->field < ARRAY_SIZE(header_field));
1179                field = header_field[p->field].field;
1180                len = header_field[p->field].len;
1181                if (strncmp(bol, field, len))
1182                        return 0;
1183                bol += len;
1184                switch (p->field) {
1185                case GREP_HEADER_AUTHOR:
1186                case GREP_HEADER_COMMITTER:
1187                        saved_ch = strip_timestamp(bol, &eol);
1188                        break;
1189                default:
1190                        break;
1191                }
1192        }
1193
1194 again:
1195        hit = patmatch(p, bol, eol, pmatch, eflags);
1196
1197        if (hit && p->word_regexp) {
1198                if ((pmatch[0].rm_so < 0) ||
1199                    (eol - bol) < pmatch[0].rm_so ||
1200                    (pmatch[0].rm_eo < 0) ||
1201                    (eol - bol) < pmatch[0].rm_eo)
1202                        die("regexp returned nonsense");
1203
1204                /* Match beginning must be either beginning of the
1205                 * line, or at word boundary (i.e. the last char must
1206                 * not be a word char).  Similarly, match end must be
1207                 * either end of the line, or at word boundary
1208                 * (i.e. the next char must not be a word char).
1209                 */
1210                if ( ((pmatch[0].rm_so == 0) ||
1211                      !word_char(bol[pmatch[0].rm_so-1])) &&
1212                     ((pmatch[0].rm_eo == (eol-bol)) ||
1213                      !word_char(bol[pmatch[0].rm_eo])) )
1214                        ;
1215                else
1216                        hit = 0;
1217
1218                /* Words consist of at least one character. */
1219                if (pmatch->rm_so == pmatch->rm_eo)
1220                        hit = 0;
1221
1222                if (!hit && pmatch[0].rm_so + bol + 1 < eol) {
1223                        /* There could be more than one match on the
1224                         * line, and the first match might not be
1225                         * strict word match.  But later ones could be!
1226                         * Forward to the next possible start, i.e. the
1227                         * next position following a non-word char.
1228                         */
1229                        bol = pmatch[0].rm_so + bol + 1;
1230                        while (word_char(bol[-1]) && bol < eol)
1231                                bol++;
1232                        eflags |= REG_NOTBOL;
1233                        if (bol < eol)
1234                                goto again;
1235                }
1236        }
1237        if (p->token == GREP_PATTERN_HEAD && saved_ch)
1238                *eol = saved_ch;
1239        if (hit) {
1240                pmatch[0].rm_so += bol - start;
1241                pmatch[0].rm_eo += bol - start;
1242        }
1243        return hit;
1244}
1245
1246static int match_expr_eval(struct grep_expr *x, char *bol, char *eol,
1247                           enum grep_context ctx, int collect_hits)
1248{
1249        int h = 0;
1250        regmatch_t match;
1251
1252        if (!x)
1253                die("Not a valid grep expression");
1254        switch (x->node) {
1255        case GREP_NODE_TRUE:
1256                h = 1;
1257                break;
1258        case GREP_NODE_ATOM:
1259                h = match_one_pattern(x->u.atom, bol, eol, ctx, &match, 0);
1260                break;
1261        case GREP_NODE_NOT:
1262                h = !match_expr_eval(x->u.unary, bol, eol, ctx, 0);
1263                break;
1264        case GREP_NODE_AND:
1265                if (!match_expr_eval(x->u.binary.left, bol, eol, ctx, 0))
1266                        return 0;
1267                h = match_expr_eval(x->u.binary.right, bol, eol, ctx, 0);
1268                break;
1269        case GREP_NODE_OR:
1270                if (!collect_hits)
1271                        return (match_expr_eval(x->u.binary.left,
1272                                                bol, eol, ctx, 0) ||
1273                                match_expr_eval(x->u.binary.right,
1274                                                bol, eol, ctx, 0));
1275                h = match_expr_eval(x->u.binary.left, bol, eol, ctx, 0);
1276                x->u.binary.left->hit |= h;
1277                h |= match_expr_eval(x->u.binary.right, bol, eol, ctx, 1);
1278                break;
1279        default:
1280                die("Unexpected node type (internal error) %d", x->node);
1281        }
1282        if (collect_hits)
1283                x->hit |= h;
1284        return h;
1285}
1286
1287static int match_expr(struct grep_opt *opt, char *bol, char *eol,
1288                      enum grep_context ctx, int collect_hits)
1289{
1290        struct grep_expr *x = opt->pattern_expression;
1291        return match_expr_eval(x, bol, eol, ctx, collect_hits);
1292}
1293
1294static int match_line(struct grep_opt *opt, char *bol, char *eol,
1295                      enum grep_context ctx, int collect_hits)
1296{
1297        struct grep_pat *p;
1298        regmatch_t match;
1299
1300        if (opt->extended)
1301                return match_expr(opt, bol, eol, ctx, collect_hits);
1302
1303        /* we do not call with collect_hits without being extended */
1304        for (p = opt->pattern_list; p; p = p->next) {
1305                if (match_one_pattern(p, bol, eol, ctx, &match, 0))
1306                        return 1;
1307        }
1308        return 0;
1309}
1310
1311static int match_next_pattern(struct grep_pat *p, char *bol, char *eol,
1312                              enum grep_context ctx,
1313                              regmatch_t *pmatch, int eflags)
1314{
1315        regmatch_t match;
1316
1317        if (!match_one_pattern(p, bol, eol, ctx, &match, eflags))
1318                return 0;
1319        if (match.rm_so < 0 || match.rm_eo < 0)
1320                return 0;
1321        if (pmatch->rm_so >= 0 && pmatch->rm_eo >= 0) {
1322                if (match.rm_so > pmatch->rm_so)
1323                        return 1;
1324                if (match.rm_so == pmatch->rm_so && match.rm_eo < pmatch->rm_eo)
1325                        return 1;
1326        }
1327        pmatch->rm_so = match.rm_so;
1328        pmatch->rm_eo = match.rm_eo;
1329        return 1;
1330}
1331
1332static int next_match(struct grep_opt *opt, char *bol, char *eol,
1333                      enum grep_context ctx, regmatch_t *pmatch, int eflags)
1334{
1335        struct grep_pat *p;
1336        int hit = 0;
1337
1338        pmatch->rm_so = pmatch->rm_eo = -1;
1339        if (bol < eol) {
1340                for (p = opt->pattern_list; p; p = p->next) {
1341                        switch (p->token) {
1342                        case GREP_PATTERN: /* atom */
1343                        case GREP_PATTERN_HEAD:
1344                        case GREP_PATTERN_BODY:
1345                                hit |= match_next_pattern(p, bol, eol, ctx,
1346                                                          pmatch, eflags);
1347                                break;
1348                        default:
1349                                break;
1350                        }
1351                }
1352        }
1353        return hit;
1354}
1355
1356static void show_line(struct grep_opt *opt, char *bol, char *eol,
1357                      const char *name, unsigned lno, char sign)
1358{
1359        int rest = eol - bol;
1360        const char *match_color, *line_color = NULL;
1361
1362        if (opt->file_break && opt->last_shown == 0) {
1363                if (opt->show_hunk_mark)
1364                        opt->output(opt, "\n", 1);
1365        } else if (opt->pre_context || opt->post_context || opt->funcbody) {
1366                if (opt->last_shown == 0) {
1367                        if (opt->show_hunk_mark) {
1368                                output_color(opt, "--", 2, opt->colors[GREP_COLOR_SEP]);
1369                                opt->output(opt, "\n", 1);
1370                        }
1371                } else if (lno > opt->last_shown + 1) {
1372                        output_color(opt, "--", 2, opt->colors[GREP_COLOR_SEP]);
1373                        opt->output(opt, "\n", 1);
1374                }
1375        }
1376        if (opt->heading && opt->last_shown == 0) {
1377                output_color(opt, name, strlen(name), opt->colors[GREP_COLOR_FILENAME]);
1378                opt->output(opt, "\n", 1);
1379        }
1380        opt->last_shown = lno;
1381
1382        if (!opt->heading && opt->pathname) {
1383                output_color(opt, name, strlen(name), opt->colors[GREP_COLOR_FILENAME]);
1384                output_sep(opt, sign);
1385        }
1386        if (opt->linenum) {
1387                char buf[32];
1388                xsnprintf(buf, sizeof(buf), "%d", lno);
1389                output_color(opt, buf, strlen(buf), opt->colors[GREP_COLOR_LINENO]);
1390                output_sep(opt, sign);
1391        }
1392        if (opt->color) {
1393                regmatch_t match;
1394                enum grep_context ctx = GREP_CONTEXT_BODY;
1395                int ch = *eol;
1396                int eflags = 0;
1397
1398                if (sign == ':')
1399                        match_color = opt->colors[GREP_COLOR_MATCH_SELECTED];
1400                else
1401                        match_color = opt->colors[GREP_COLOR_MATCH_CONTEXT];
1402                if (sign == ':')
1403                        line_color = opt->colors[GREP_COLOR_SELECTED];
1404                else if (sign == '-')
1405                        line_color = opt->colors[GREP_COLOR_CONTEXT];
1406                else if (sign == '=')
1407                        line_color = opt->colors[GREP_COLOR_FUNCTION];
1408                *eol = '\0';
1409                while (next_match(opt, bol, eol, ctx, &match, eflags)) {
1410                        if (match.rm_so == match.rm_eo)
1411                                break;
1412
1413                        output_color(opt, bol, match.rm_so, line_color);
1414                        output_color(opt, bol + match.rm_so,
1415                                     match.rm_eo - match.rm_so, match_color);
1416                        bol += match.rm_eo;
1417                        rest -= match.rm_eo;
1418                        eflags = REG_NOTBOL;
1419                }
1420                *eol = ch;
1421        }
1422        output_color(opt, bol, rest, line_color);
1423        opt->output(opt, "\n", 1);
1424}
1425
1426#ifndef NO_PTHREADS
1427int grep_use_locks;
1428
1429/*
1430 * This lock protects access to the gitattributes machinery, which is
1431 * not thread-safe.
1432 */
1433pthread_mutex_t grep_attr_mutex;
1434
1435static inline void grep_attr_lock(void)
1436{
1437        if (grep_use_locks)
1438                pthread_mutex_lock(&grep_attr_mutex);
1439}
1440
1441static inline void grep_attr_unlock(void)
1442{
1443        if (grep_use_locks)
1444                pthread_mutex_unlock(&grep_attr_mutex);
1445}
1446
1447/*
1448 * Same as git_attr_mutex, but protecting the thread-unsafe object db access.
1449 */
1450pthread_mutex_t grep_read_mutex;
1451
1452#else
1453#define grep_attr_lock()
1454#define grep_attr_unlock()
1455#endif
1456
1457static int match_funcname(struct grep_opt *opt, struct grep_source *gs, char *bol, char *eol)
1458{
1459        xdemitconf_t *xecfg = opt->priv;
1460        if (xecfg && !xecfg->find_func) {
1461                grep_source_load_driver(gs);
1462                if (gs->driver->funcname.pattern) {
1463                        const struct userdiff_funcname *pe = &gs->driver->funcname;
1464                        xdiff_set_find_func(xecfg, pe->pattern, pe->cflags);
1465                } else {
1466                        xecfg = opt->priv = NULL;
1467                }
1468        }
1469
1470        if (xecfg) {
1471                char buf[1];
1472                return xecfg->find_func(bol, eol - bol, buf, 1,
1473                                        xecfg->find_func_priv) >= 0;
1474        }
1475
1476        if (bol == eol)
1477                return 0;
1478        if (isalpha(*bol) || *bol == '_' || *bol == '$')
1479                return 1;
1480        return 0;
1481}
1482
1483static void show_funcname_line(struct grep_opt *opt, struct grep_source *gs,
1484                               char *bol, unsigned lno)
1485{
1486        while (bol > gs->buf) {
1487                char *eol = --bol;
1488
1489                while (bol > gs->buf && bol[-1] != '\n')
1490                        bol--;
1491                lno--;
1492
1493                if (lno <= opt->last_shown)
1494                        break;
1495
1496                if (match_funcname(opt, gs, bol, eol)) {
1497                        show_line(opt, bol, eol, gs->name, lno, '=');
1498                        break;
1499                }
1500        }
1501}
1502
1503static int is_empty_line(const char *bol, const char *eol);
1504
1505static void show_pre_context(struct grep_opt *opt, struct grep_source *gs,
1506                             char *bol, char *end, unsigned lno)
1507{
1508        unsigned cur = lno, from = 1, funcname_lno = 0, orig_from;
1509        int funcname_needed = !!opt->funcname, comment_needed = 0;
1510
1511        if (opt->pre_context < lno)
1512                from = lno - opt->pre_context;
1513        if (from <= opt->last_shown)
1514                from = opt->last_shown + 1;
1515        orig_from = from;
1516        if (opt->funcbody) {
1517                if (match_funcname(opt, gs, bol, end))
1518                        comment_needed = 1;
1519                else
1520                        funcname_needed = 1;
1521                from = opt->last_shown + 1;
1522        }
1523
1524        /* Rewind. */
1525        while (bol > gs->buf && cur > from) {
1526                char *next_bol = bol;
1527                char *eol = --bol;
1528
1529                while (bol > gs->buf && bol[-1] != '\n')
1530                        bol--;
1531                cur--;
1532                if (comment_needed && (is_empty_line(bol, eol) ||
1533                                       match_funcname(opt, gs, bol, eol))) {
1534                        comment_needed = 0;
1535                        from = orig_from;
1536                        if (cur < from) {
1537                                cur++;
1538                                bol = next_bol;
1539                                break;
1540                        }
1541                }
1542                if (funcname_needed && match_funcname(opt, gs, bol, eol)) {
1543                        funcname_lno = cur;
1544                        funcname_needed = 0;
1545                        if (opt->funcbody)
1546                                comment_needed = 1;
1547                        else
1548                                from = orig_from;
1549                }
1550        }
1551
1552        /* We need to look even further back to find a function signature. */
1553        if (opt->funcname && funcname_needed)
1554                show_funcname_line(opt, gs, bol, cur);
1555
1556        /* Back forward. */
1557        while (cur < lno) {
1558                char *eol = bol, sign = (cur == funcname_lno) ? '=' : '-';
1559
1560                while (*eol != '\n')
1561                        eol++;
1562                show_line(opt, bol, eol, gs->name, cur, sign);
1563                bol = eol + 1;
1564                cur++;
1565        }
1566}
1567
1568static int should_lookahead(struct grep_opt *opt)
1569{
1570        struct grep_pat *p;
1571
1572        if (opt->extended)
1573                return 0; /* punt for too complex stuff */
1574        if (opt->invert)
1575                return 0;
1576        for (p = opt->pattern_list; p; p = p->next) {
1577                if (p->token != GREP_PATTERN)
1578                        return 0; /* punt for "header only" and stuff */
1579        }
1580        return 1;
1581}
1582
1583static int look_ahead(struct grep_opt *opt,
1584                      unsigned long *left_p,
1585                      unsigned *lno_p,
1586                      char **bol_p)
1587{
1588        unsigned lno = *lno_p;
1589        char *bol = *bol_p;
1590        struct grep_pat *p;
1591        char *sp, *last_bol;
1592        regoff_t earliest = -1;
1593
1594        for (p = opt->pattern_list; p; p = p->next) {
1595                int hit;
1596                regmatch_t m;
1597
1598                hit = patmatch(p, bol, bol + *left_p, &m, 0);
1599                if (!hit || m.rm_so < 0 || m.rm_eo < 0)
1600                        continue;
1601                if (earliest < 0 || m.rm_so < earliest)
1602                        earliest = m.rm_so;
1603        }
1604
1605        if (earliest < 0) {
1606                *bol_p = bol + *left_p;
1607                *left_p = 0;
1608                return 1;
1609        }
1610        for (sp = bol + earliest; bol < sp && sp[-1] != '\n'; sp--)
1611                ; /* find the beginning of the line */
1612        last_bol = sp;
1613
1614        for (sp = bol; sp < last_bol; sp++) {
1615                if (*sp == '\n')
1616                        lno++;
1617        }
1618        *left_p -= last_bol - bol;
1619        *bol_p = last_bol;
1620        *lno_p = lno;
1621        return 0;
1622}
1623
1624static int fill_textconv_grep(struct userdiff_driver *driver,
1625                              struct grep_source *gs)
1626{
1627        struct diff_filespec *df;
1628        char *buf;
1629        size_t size;
1630
1631        if (!driver || !driver->textconv)
1632                return grep_source_load(gs);
1633
1634        /*
1635         * The textconv interface is intimately tied to diff_filespecs, so we
1636         * have to pretend to be one. If we could unify the grep_source
1637         * and diff_filespec structs, this mess could just go away.
1638         */
1639        df = alloc_filespec(gs->path);
1640        switch (gs->type) {
1641        case GREP_SOURCE_OID:
1642                fill_filespec(df, gs->identifier, 1, 0100644);
1643                break;
1644        case GREP_SOURCE_FILE:
1645                fill_filespec(df, &null_oid, 0, 0100644);
1646                break;
1647        default:
1648                BUG("attempt to textconv something without a path?");
1649        }
1650
1651        /*
1652         * fill_textconv is not remotely thread-safe; it may load objects
1653         * behind the scenes, and it modifies the global diff tempfile
1654         * structure.
1655         */
1656        grep_read_lock();
1657        size = fill_textconv(driver, df, &buf);
1658        grep_read_unlock();
1659        free_filespec(df);
1660
1661        /*
1662         * The normal fill_textconv usage by the diff machinery would just keep
1663         * the textconv'd buf separate from the diff_filespec. But much of the
1664         * grep code passes around a grep_source and assumes that its "buf"
1665         * pointer is the beginning of the thing we are searching. So let's
1666         * install our textconv'd version into the grep_source, taking care not
1667         * to leak any existing buffer.
1668         */
1669        grep_source_clear_data(gs);
1670        gs->buf = buf;
1671        gs->size = size;
1672
1673        return 0;
1674}
1675
1676static int is_empty_line(const char *bol, const char *eol)
1677{
1678        while (bol < eol && isspace(*bol))
1679                bol++;
1680        return bol == eol;
1681}
1682
1683static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int collect_hits)
1684{
1685        char *bol;
1686        char *peek_bol = NULL;
1687        unsigned long left;
1688        unsigned lno = 1;
1689        unsigned last_hit = 0;
1690        int binary_match_only = 0;
1691        unsigned count = 0;
1692        int try_lookahead = 0;
1693        int show_function = 0;
1694        struct userdiff_driver *textconv = NULL;
1695        enum grep_context ctx = GREP_CONTEXT_HEAD;
1696        xdemitconf_t xecfg;
1697
1698        if (!opt->output)
1699                opt->output = std_output;
1700
1701        if (opt->pre_context || opt->post_context || opt->file_break ||
1702            opt->funcbody) {
1703                /* Show hunk marks, except for the first file. */
1704                if (opt->last_shown)
1705                        opt->show_hunk_mark = 1;
1706                /*
1707                 * If we're using threads then we can't easily identify
1708                 * the first file.  Always put hunk marks in that case
1709                 * and skip the very first one later in work_done().
1710                 */
1711                if (opt->output != std_output)
1712                        opt->show_hunk_mark = 1;
1713        }
1714        opt->last_shown = 0;
1715
1716        if (opt->allow_textconv) {
1717                grep_source_load_driver(gs);
1718                /*
1719                 * We might set up the shared textconv cache data here, which
1720                 * is not thread-safe.
1721                 */
1722                grep_attr_lock();
1723                textconv = userdiff_get_textconv(gs->driver);
1724                grep_attr_unlock();
1725        }
1726
1727        /*
1728         * We know the result of a textconv is text, so we only have to care
1729         * about binary handling if we are not using it.
1730         */
1731        if (!textconv) {
1732                switch (opt->binary) {
1733                case GREP_BINARY_DEFAULT:
1734                        if (grep_source_is_binary(gs))
1735                                binary_match_only = 1;
1736                        break;
1737                case GREP_BINARY_NOMATCH:
1738                        if (grep_source_is_binary(gs))
1739                                return 0; /* Assume unmatch */
1740                        break;
1741                case GREP_BINARY_TEXT:
1742                        break;
1743                default:
1744                        BUG("unknown binary handling mode");
1745                }
1746        }
1747
1748        memset(&xecfg, 0, sizeof(xecfg));
1749        opt->priv = &xecfg;
1750
1751        try_lookahead = should_lookahead(opt);
1752
1753        if (fill_textconv_grep(textconv, gs) < 0)
1754                return 0;
1755
1756        bol = gs->buf;
1757        left = gs->size;
1758        while (left) {
1759                char *eol, ch;
1760                int hit;
1761
1762                /*
1763                 * look_ahead() skips quickly to the line that possibly
1764                 * has the next hit; don't call it if we need to do
1765                 * something more than just skipping the current line
1766                 * in response to an unmatch for the current line.  E.g.
1767                 * inside a post-context window, we will show the current
1768                 * line as a context around the previous hit when it
1769                 * doesn't hit.
1770                 */
1771                if (try_lookahead
1772                    && !(last_hit
1773                         && (show_function ||
1774                             lno <= last_hit + opt->post_context))
1775                    && look_ahead(opt, &left, &lno, &bol))
1776                        break;
1777                eol = end_of_line(bol, &left);
1778                ch = *eol;
1779                *eol = 0;
1780
1781                if ((ctx == GREP_CONTEXT_HEAD) && (eol == bol))
1782                        ctx = GREP_CONTEXT_BODY;
1783
1784                hit = match_line(opt, bol, eol, ctx, collect_hits);
1785                *eol = ch;
1786
1787                if (collect_hits)
1788                        goto next_line;
1789
1790                /* "grep -v -e foo -e bla" should list lines
1791                 * that do not have either, so inversion should
1792                 * be done outside.
1793                 */
1794                if (opt->invert)
1795                        hit = !hit;
1796                if (opt->unmatch_name_only) {
1797                        if (hit)
1798                                return 0;
1799                        goto next_line;
1800                }
1801                if (hit) {
1802                        count++;
1803                        if (opt->status_only)
1804                                return 1;
1805                        if (opt->name_only) {
1806                                show_name(opt, gs->name);
1807                                return 1;
1808                        }
1809                        if (opt->count)
1810                                goto next_line;
1811                        if (binary_match_only) {
1812                                opt->output(opt, "Binary file ", 12);
1813                                output_color(opt, gs->name, strlen(gs->name),
1814                                             opt->colors[GREP_COLOR_FILENAME]);
1815                                opt->output(opt, " matches\n", 9);
1816                                return 1;
1817                        }
1818                        /* Hit at this line.  If we haven't shown the
1819                         * pre-context lines, we would need to show them.
1820                         */
1821                        if (opt->pre_context || opt->funcbody)
1822                                show_pre_context(opt, gs, bol, eol, lno);
1823                        else if (opt->funcname)
1824                                show_funcname_line(opt, gs, bol, lno);
1825                        show_line(opt, bol, eol, gs->name, lno, ':');
1826                        last_hit = lno;
1827                        if (opt->funcbody)
1828                                show_function = 1;
1829                        goto next_line;
1830                }
1831                if (show_function && (!peek_bol || peek_bol < bol)) {
1832                        unsigned long peek_left = left;
1833                        char *peek_eol = eol;
1834
1835                        /*
1836                         * Trailing empty lines are not interesting.
1837                         * Peek past them to see if they belong to the
1838                         * body of the current function.
1839                         */
1840                        peek_bol = bol;
1841                        while (is_empty_line(peek_bol, peek_eol)) {
1842                                peek_bol = peek_eol + 1;
1843                                peek_eol = end_of_line(peek_bol, &peek_left);
1844                        }
1845
1846                        if (match_funcname(opt, gs, peek_bol, peek_eol))
1847                                show_function = 0;
1848                }
1849                if (show_function ||
1850                    (last_hit && lno <= last_hit + opt->post_context)) {
1851                        /* If the last hit is within the post context,
1852                         * we need to show this line.
1853                         */
1854                        show_line(opt, bol, eol, gs->name, lno, '-');
1855                }
1856
1857        next_line:
1858                bol = eol + 1;
1859                if (!left)
1860                        break;
1861                left--;
1862                lno++;
1863        }
1864
1865        if (collect_hits)
1866                return 0;
1867
1868        if (opt->status_only)
1869                return opt->unmatch_name_only;
1870        if (opt->unmatch_name_only) {
1871                /* We did not see any hit, so we want to show this */
1872                show_name(opt, gs->name);
1873                return 1;
1874        }
1875
1876        xdiff_clear_find_func(&xecfg);
1877        opt->priv = NULL;
1878
1879        /* NEEDSWORK:
1880         * The real "grep -c foo *.c" gives many "bar.c:0" lines,
1881         * which feels mostly useless but sometimes useful.  Maybe
1882         * make it another option?  For now suppress them.
1883         */
1884        if (opt->count && count) {
1885                char buf[32];
1886                if (opt->pathname) {
1887                        output_color(opt, gs->name, strlen(gs->name),
1888                                     opt->colors[GREP_COLOR_FILENAME]);
1889                        output_sep(opt, ':');
1890                }
1891                xsnprintf(buf, sizeof(buf), "%u\n", count);
1892                opt->output(opt, buf, strlen(buf));
1893                return 1;
1894        }
1895        return !!last_hit;
1896}
1897
1898static void clr_hit_marker(struct grep_expr *x)
1899{
1900        /* All-hit markers are meaningful only at the very top level
1901         * OR node.
1902         */
1903        while (1) {
1904                x->hit = 0;
1905                if (x->node != GREP_NODE_OR)
1906                        return;
1907                x->u.binary.left->hit = 0;
1908                x = x->u.binary.right;
1909        }
1910}
1911
1912static int chk_hit_marker(struct grep_expr *x)
1913{
1914        /* Top level nodes have hit markers.  See if they all are hits */
1915        while (1) {
1916                if (x->node != GREP_NODE_OR)
1917                        return x->hit;
1918                if (!x->u.binary.left->hit)
1919                        return 0;
1920                x = x->u.binary.right;
1921        }
1922}
1923
1924int grep_source(struct grep_opt *opt, struct grep_source *gs)
1925{
1926        /*
1927         * we do not have to do the two-pass grep when we do not check
1928         * buffer-wide "all-match".
1929         */
1930        if (!opt->all_match)
1931                return grep_source_1(opt, gs, 0);
1932
1933        /* Otherwise the toplevel "or" terms hit a bit differently.
1934         * We first clear hit markers from them.
1935         */
1936        clr_hit_marker(opt->pattern_expression);
1937        grep_source_1(opt, gs, 1);
1938
1939        if (!chk_hit_marker(opt->pattern_expression))
1940                return 0;
1941
1942        return grep_source_1(opt, gs, 0);
1943}
1944
1945int grep_buffer(struct grep_opt *opt, char *buf, unsigned long size)
1946{
1947        struct grep_source gs;
1948        int r;
1949
1950        grep_source_init(&gs, GREP_SOURCE_BUF, NULL, NULL, NULL);
1951        gs.buf = buf;
1952        gs.size = size;
1953
1954        r = grep_source(opt, &gs);
1955
1956        grep_source_clear(&gs);
1957        return r;
1958}
1959
1960void grep_source_init(struct grep_source *gs, enum grep_source_type type,
1961                      const char *name, const char *path,
1962                      const void *identifier)
1963{
1964        gs->type = type;
1965        gs->name = xstrdup_or_null(name);
1966        gs->path = xstrdup_or_null(path);
1967        gs->buf = NULL;
1968        gs->size = 0;
1969        gs->driver = NULL;
1970
1971        switch (type) {
1972        case GREP_SOURCE_FILE:
1973                gs->identifier = xstrdup(identifier);
1974                break;
1975        case GREP_SOURCE_OID:
1976                gs->identifier = oiddup(identifier);
1977                break;
1978        case GREP_SOURCE_BUF:
1979                gs->identifier = NULL;
1980                break;
1981        }
1982}
1983
1984void grep_source_clear(struct grep_source *gs)
1985{
1986        FREE_AND_NULL(gs->name);
1987        FREE_AND_NULL(gs->path);
1988        FREE_AND_NULL(gs->identifier);
1989        grep_source_clear_data(gs);
1990}
1991
1992void grep_source_clear_data(struct grep_source *gs)
1993{
1994        switch (gs->type) {
1995        case GREP_SOURCE_FILE:
1996        case GREP_SOURCE_OID:
1997                FREE_AND_NULL(gs->buf);
1998                gs->size = 0;
1999                break;
2000        case GREP_SOURCE_BUF:
2001                /* leave user-provided buf intact */
2002                break;
2003        }
2004}
2005
2006static int grep_source_load_oid(struct grep_source *gs)
2007{
2008        enum object_type type;
2009
2010        grep_read_lock();
2011        gs->buf = read_object_file(gs->identifier, &type, &gs->size);
2012        grep_read_unlock();
2013
2014        if (!gs->buf)
2015                return error(_("'%s': unable to read %s"),
2016                             gs->name,
2017                             oid_to_hex(gs->identifier));
2018        return 0;
2019}
2020
2021static int grep_source_load_file(struct grep_source *gs)
2022{
2023        const char *filename = gs->identifier;
2024        struct stat st;
2025        char *data;
2026        size_t size;
2027        int i;
2028
2029        if (lstat(filename, &st) < 0) {
2030        err_ret:
2031                if (errno != ENOENT)
2032                        error_errno(_("failed to stat '%s'"), filename);
2033                return -1;
2034        }
2035        if (!S_ISREG(st.st_mode))
2036                return -1;
2037        size = xsize_t(st.st_size);
2038        i = open(filename, O_RDONLY);
2039        if (i < 0)
2040                goto err_ret;
2041        data = xmallocz(size);
2042        if (st.st_size != read_in_full(i, data, size)) {
2043                error_errno(_("'%s': short read"), filename);
2044                close(i);
2045                free(data);
2046                return -1;
2047        }
2048        close(i);
2049
2050        gs->buf = data;
2051        gs->size = size;
2052        return 0;
2053}
2054
2055static int grep_source_load(struct grep_source *gs)
2056{
2057        if (gs->buf)
2058                return 0;
2059
2060        switch (gs->type) {
2061        case GREP_SOURCE_FILE:
2062                return grep_source_load_file(gs);
2063        case GREP_SOURCE_OID:
2064                return grep_source_load_oid(gs);
2065        case GREP_SOURCE_BUF:
2066                return gs->buf ? 0 : -1;
2067        }
2068        BUG("invalid grep_source type to load");
2069}
2070
2071void grep_source_load_driver(struct grep_source *gs)
2072{
2073        if (gs->driver)
2074                return;
2075
2076        grep_attr_lock();
2077        if (gs->path)
2078                gs->driver = userdiff_find_by_path(gs->path);
2079        if (!gs->driver)
2080                gs->driver = userdiff_find_by_name("default");
2081        grep_attr_unlock();
2082}
2083
2084static int grep_source_is_binary(struct grep_source *gs)
2085{
2086        grep_source_load_driver(gs);
2087        if (gs->driver->binary != -1)
2088                return gs->driver->binary;
2089
2090        if (!grep_source_load(gs))
2091                return buffer_is_binary(gs->buf, gs->size);
2092
2093        return 0;
2094}