[BACK]Return to util.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / grep

Annotation of src/usr.bin/grep/util.c, Revision 1.39

1.39    ! tedu        1: /*     $OpenBSD: util.c,v 1.38 2010/04/25 14:13:36 eric Exp $  */
1.3       deraadt     2:
1.1       deraadt     3: /*-
                      4:  * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     17:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     18:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     19:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     20:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     21:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     22:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     23:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     24:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     25:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     26:  * SUCH DAMAGE.
                     27:  */
                     28:
                     29: #include <sys/types.h>
                     30: #include <sys/stat.h>
                     31:
                     32: #include <ctype.h>
                     33: #include <err.h>
                     34: #include <errno.h>
                     35: #include <fts.h>
                     36: #include <regex.h>
                     37: #include <stdio.h>
                     38: #include <stdlib.h>
                     39: #include <string.h>
                     40: #include <unistd.h>
                     41: #include <zlib.h>
                     42:
                     43: #include "grep.h"
                     44:
                     45: /*
                     46:  * Process a file line by line...
                     47:  */
                     48:
                     49: static int     linesqueued;
1.4       tedu       50: static int     procline(str_t *l, int);
1.23      millert    51: static int     grep_search(fastgrep_t *, unsigned char *, size_t, regmatch_t *pmatch);
1.39    ! tedu       52: #ifndef SMALL
1.6       tedu       53: static int     grep_cmp(const unsigned char *, const unsigned char *, size_t);
                     54: static void    grep_revstr(unsigned char *, int);
1.39    ! tedu       55: #endif
1.1       deraadt    56:
1.2       deraadt    57: int
1.1       deraadt    58: grep_tree(char **argv)
                     59: {
1.10      deraadt    60:        FTS     *fts;
                     61:        FTSENT  *p;
                     62:        int     c, fts_flags;
1.1       deraadt    63:
1.37      tedu       64:        c = 0;
1.1       deraadt    65:
1.37      tedu       66:        fts_flags = FTS_PHYSICAL | FTS_NOSTAT | FTS_NOCHDIR;
1.1       deraadt    67:
1.11      millert    68:        if (!(fts = fts_open(argv, fts_flags, NULL)))
1.14      millert    69:                err(2, NULL);
1.1       deraadt    70:        while ((p = fts_read(fts)) != NULL) {
                     71:                switch (p->fts_info) {
                     72:                case FTS_DNR:
                     73:                        break;
                     74:                case FTS_ERR:
1.14      millert    75:                        errx(2, "%s: %s", p->fts_path, strerror(p->fts_errno));
1.1       deraadt    76:                        break;
                     77:                case FTS_DP:
                     78:                        break;
                     79:                default:
                     80:                        c += procfile(p->fts_path);
                     81:                        break;
                     82:                }
                     83:        }
1.34      otto       84:        if (errno)
                     85:                err(2, "fts_read");
1.1       deraadt    86:
                     87:        return c;
                     88: }
                     89:
                     90: int
                     91: procfile(char *fn)
                     92: {
                     93:        str_t ln;
                     94:        file_t *f;
1.4       tedu       95:        int c, t, z, nottext;
1.1       deraadt    96:
                     97:        if (fn == NULL) {
                     98:                fn = "(standard input)";
                     99:                f = grep_fdopen(STDIN_FILENO, "r");
                    100:        } else {
                    101:                f = grep_open(fn, "r");
                    102:        }
                    103:        if (f == NULL) {
                    104:                if (!sflag)
                    105:                        warn("%s", fn);
                    106:                return 0;
                    107:        }
1.4       tedu      108:
                    109:        nottext = grep_bin_file(f);
                    110:        if (nottext && binbehave == BIN_FILE_SKIP) {
1.1       deraadt   111:                grep_close(f);
                    112:                return 0;
                    113:        }
                    114:
                    115:        ln.file = fn;
                    116:        ln.line_no = 0;
1.20      espie     117:        ln.len = 0;
1.1       deraadt   118:        linesqueued = 0;
1.33      jaredy    119:        tail = 0;
1.1       deraadt   120:        ln.off = -1;
                    121:
                    122:        if (Bflag > 0)
                    123:                initqueue();
1.27      otto      124:        for (c = 0;  c == 0 || !(lflag || qflag); ) {
1.1       deraadt   125:                ln.off += ln.len + 1;
                    126:                if ((ln.dat = grep_fgetln(f, &ln.len)) == NULL)
                    127:                        break;
                    128:                if (ln.len > 0 && ln.dat[ln.len - 1] == '\n')
                    129:                        --ln.len;
                    130:                ln.line_no++;
                    131:
                    132:                z = tail;
1.2       deraadt   133:
1.4       tedu      134:                if ((t = procline(&ln, nottext)) == 0 && Bflag > 0 && z == 0) {
1.1       deraadt   135:                        enqueue(&ln);
                    136:                        linesqueued++;
                    137:                }
                    138:                c += t;
                    139:        }
                    140:        if (Bflag > 0)
                    141:                clearqueue();
                    142:        grep_close(f);
                    143:
                    144:        if (cflag) {
                    145:                if (!hflag)
                    146:                        printf("%s:", ln.file);
                    147:                printf("%u\n", c);
                    148:        }
                    149:        if (lflag && c != 0)
                    150:                printf("%s\n", fn);
                    151:        if (Lflag && c == 0)
                    152:                printf("%s\n", fn);
1.4       tedu      153:        if (c && !cflag && !lflag && !Lflag &&
1.7       tedu      154:            binbehave == BIN_FILE_BIN && nottext && !qflag)
1.4       tedu      155:                printf("Binary file %s matches\n", fn);
                    156:
1.1       deraadt   157:        return c;
                    158: }
                    159:
                    160:
                    161: /*
                    162:  * Process an individual line in a file. Return non-zero if it matches.
                    163:  */
                    164:
                    165: #define isword(x) (isalnum(x) || (x) == '_')
                    166:
                    167: static int
1.4       tedu      168: procline(str_t *l, int nottext)
1.1       deraadt   169: {
                    170:        regmatch_t      pmatch;
1.15      dhartmei  171:        int             c, i, r;
1.1       deraadt   172:
                    173:        if (matchall) {
                    174:                c = !vflag;
                    175:                goto print;
                    176:        }
1.2       deraadt   177:
1.1       deraadt   178:        for (c = i = 0; i < patterns; i++) {
1.22      millert   179:                if (fg_pattern[i].pattern) {
1.6       tedu      180:                        r = grep_search(&fg_pattern[i], (unsigned char *)l->dat,
1.9       millert   181:                            l->len, &pmatch);
1.22      millert   182:                } else {
                    183:                        pmatch.rm_so = 0;
                    184:                        pmatch.rm_eo = l->len;
1.9       millert   185:                        r = regexec(&r_pattern[i], l->dat, 1, &pmatch, eflags);
1.22      millert   186:                }
                    187:                if (r == 0 && xflag) {
                    188:                        if (pmatch.rm_so != 0 || pmatch.rm_eo != l->len)
                    189:                                r = REG_NOMATCH;
1.1       deraadt   190:                }
1.15      dhartmei  191:                if (r == 0) {
1.1       deraadt   192:                        c++;
                    193:                        break;
                    194:                }
                    195:        }
1.15      dhartmei  196:        if (vflag)
                    197:                c = !c;
1.2       deraadt   198:
1.1       deraadt   199: print:
1.4       tedu      200:        if (c && binbehave == BIN_FILE_BIN && nottext)
                    201:                return c; /* Binary file */
                    202:
1.1       deraadt   203:        if ((tail > 0 || c) && !cflag && !qflag) {
                    204:                if (c) {
1.5       deraadt   205:                        if (first > 0 && tail == 0 && (Bflag < linesqueued) &&
                    206:                            (Aflag || Bflag))
1.1       deraadt   207:                                printf("--\n");
                    208:                        first = 1;
                    209:                        tail = Aflag;
                    210:                        if (Bflag > 0)
                    211:                                printqueue();
                    212:                        linesqueued = 0;
                    213:                        printline(l, ':');
                    214:                } else {
                    215:                        printline(l, '-');
                    216:                        tail--;
                    217:                }
                    218:        }
                    219:        return c;
                    220: }
                    221:
1.39    ! tedu      222: #ifndef SMALL
1.31      otto      223: void
1.25      millert   224: fgrepcomp(fastgrep_t *fg, const char *pattern)
                    225: {
                    226:        int i;
                    227:
                    228:        /* Initialize. */
                    229:        fg->patternLen = strlen(pattern);
                    230:        fg->bol = 0;
                    231:        fg->eol = 0;
                    232:        fg->wmatch = wflag;
                    233:        fg->reversedSearch = 0;
                    234:
                    235:        /*
                    236:         * Make a copy and upper case it for later if in -i mode,
                    237:         * else just copy the pointer.
                    238:         */
                    239:        if (iflag) {
                    240:                fg->pattern = grep_malloc(fg->patternLen + 1);
                    241:                for (i = 0; i < fg->patternLen; i++)
                    242:                        fg->pattern[i] = toupper(pattern[i]);
                    243:                fg->pattern[fg->patternLen] = '\0';
                    244:        } else
1.28      deraadt   245:                fg->pattern = (unsigned char *)pattern; /* really const */
1.25      millert   246:
                    247:        /* Preprocess pattern. */
                    248:        for (i = 0; i <= UCHAR_MAX; i++)
                    249:                fg->qsBc[i] = fg->patternLen;
                    250:        for (i = 1; i < fg->patternLen; i++) {
                    251:                fg->qsBc[fg->pattern[i]] = fg->patternLen - i;
                    252:                /*
                    253:                 * If case is ignored, make the jump apply to both upper and
                    254:                 * lower cased characters.  As the pattern is stored in upper
                    255:                 * case, apply the same to the lower case equivalents.
                    256:                 */
                    257:                if (iflag)
                    258:                        fg->qsBc[tolower(fg->pattern[i])] = fg->patternLen - i;
                    259:        }
                    260: }
1.39    ! tedu      261: #endif
1.25      millert   262:
                    263: /*
                    264:  * Returns: -1 on failure, 0 on success
                    265:  */
                    266: int
1.6       tedu      267: fastcomp(fastgrep_t *fg, const char *pattern)
                    268: {
1.39    ! tedu      269: #ifdef SMALL
        !           270:        return -1;
        !           271: #else
1.6       tedu      272:        int i;
                    273:        int bol = 0;
                    274:        int eol = 0;
                    275:        int shiftPatternLen;
                    276:        int hasDot = 0;
                    277:        int firstHalfDot = -1;
                    278:        int firstLastHalfDot = -1;
                    279:        int lastHalfDot = 0;
                    280:
                    281:        /* Initialize. */
1.28      deraadt   282:        fg->patternLen = strlen(pattern);
1.6       tedu      283:        fg->bol = 0;
                    284:        fg->eol = 0;
1.22      millert   285:        fg->wmatch = 0;
1.6       tedu      286:        fg->reversedSearch = 0;
                    287:
                    288:        /* Remove end-of-line character ('$'). */
1.38      eric      289:        if (fg->patternLen > 0 && pattern[fg->patternLen - 1] == '$') {
1.6       tedu      290:                eol++;
                    291:                fg->eol = 1;
                    292:                fg->patternLen--;
                    293:        }
                    294:
                    295:        /* Remove beginning-of-line character ('^'). */
                    296:        if (pattern[0] == '^') {
                    297:                bol++;
                    298:                fg->bol = 1;
                    299:                fg->patternLen--;
                    300:        }
                    301:
1.22      millert   302:        /* Remove enclosing [[:<:]] and [[:>:]] (word match). */
1.30      otto      303:        if (wflag) {
                    304:                /* basic re's use \( \), extended re's ( ) */
                    305:                int extra = Eflag ? 1 : 2;
                    306:                fg->patternLen -= 14 + 2 * extra;
                    307:                fg->wmatch = 7 + extra;
                    308:        } else if (fg->patternLen >= 14 &&
1.22      millert   309:            strncmp(pattern + fg->bol, "[[:<:]]", 7) == 0 &&
1.24      millert   310:            strncmp(pattern + fg->bol + fg->patternLen - 7, "[[:>:]]", 7) == 0) {
1.22      millert   311:                fg->patternLen -= 14;
                    312:                fg->wmatch = 7;
                    313:        }
                    314:
1.6       tedu      315:        /*
1.22      millert   316:         * Copy pattern minus '^' and '$' characters as well as word
                    317:         * match character classes at the beginning and ending of the
                    318:         * string respectively.
1.6       tedu      319:         */
1.22      millert   320:        fg->pattern = grep_malloc(fg->patternLen + 1);
                    321:        memcpy(fg->pattern, pattern + bol + fg->wmatch, fg->patternLen);
                    322:        fg->pattern[fg->patternLen] = '\0';
1.6       tedu      323:
                    324:        /* Look for ways to cheat...er...avoid the full regex engine. */
                    325:        for (i = 0; i < fg->patternLen; i++)
                    326:        {
                    327:                /* Can still cheat? */
                    328:                if ((isalnum(fg->pattern[i])) || isspace(fg->pattern[i]) ||
                    329:                    (fg->pattern[i] == '_') || (fg->pattern[i] == ',') ||
                    330:                    (fg->pattern[i] == '=') || (fg->pattern[i] == '-') ||
                    331:                    (fg->pattern[i] == ':') || (fg->pattern[i] == '/')) {
                    332:                        /* As long as it is good, upper case it for later. */
                    333:                        if (iflag)
                    334:                                fg->pattern[i] = toupper(fg->pattern[i]);
                    335:                } else if (fg->pattern[i] == '.') {
                    336:                        hasDot = i;
                    337:                        if (i < fg->patternLen / 2) {
1.19      otto      338:                                if (firstHalfDot < 0)
1.6       tedu      339:                                        /* Closest dot to the beginning */
                    340:                                        firstHalfDot = i;
                    341:                        } else {
                    342:                                /* Closest dot to the end of the pattern. */
                    343:                                lastHalfDot = i;
                    344:                                if (firstLastHalfDot < 0)
                    345:                                        firstLastHalfDot = i;
                    346:                        }
                    347:                } else {
                    348:                        /* Free memory and let others know this is empty. */
                    349:                        free(fg->pattern);
                    350:                        fg->pattern = NULL;
                    351:                        return (-1);
                    352:                }
                    353:        }
                    354:
                    355:        /*
                    356:         * Determine if a reverse search would be faster based on the placement
                    357:         * of the dots.
                    358:         */
                    359:        if ((!(lflag || cflag)) && ((!(bol || eol)) &&
                    360:            ((lastHalfDot) && ((firstHalfDot < 0) ||
                    361:            ((fg->patternLen - (lastHalfDot + 1)) < firstHalfDot))))) {
                    362:                fg->reversedSearch = 1;
                    363:                hasDot = fg->patternLen - (firstHalfDot < 0 ?
                    364:                    firstLastHalfDot : firstHalfDot) - 1;
                    365:                grep_revstr(fg->pattern, fg->patternLen);
                    366:        }
                    367:
                    368:        /*
                    369:         * Normal Quick Search would require a shift based on the position the
                    370:         * next character after the comparison is within the pattern.  With
                    371:         * wildcards, the position of the last dot effects the maximum shift
                    372:         * distance.
                    373:         * The closer to the end the wild card is the slower the search.  A
1.10      deraadt   374:         * reverse version of this algorithm would be useful for wildcards near
1.6       tedu      375:         * the end of the string.
                    376:         *
                    377:         * Examples:
                    378:         * Pattern      Max shift
                    379:         * -------      ---------
                    380:         * this         5
                    381:         * .his         4
                    382:         * t.is         3
                    383:         * th.s         2
                    384:         * thi.         1
                    385:         */
                    386:
                    387:        /* Adjust the shift based on location of the last dot ('.'). */
                    388:        shiftPatternLen = fg->patternLen - hasDot;
                    389:
                    390:        /* Preprocess pattern. */
                    391:        for (i = 0; i <= UCHAR_MAX; i++)
                    392:                fg->qsBc[i] = shiftPatternLen;
                    393:        for (i = hasDot + 1; i < fg->patternLen; i++) {
                    394:                fg->qsBc[fg->pattern[i]] = fg->patternLen - i;
                    395:                /*
                    396:                 * If case is ignored, make the jump apply to both upper and
                    397:                 * lower cased characters.  As the pattern is stored in upper
                    398:                 * case, apply the same to the lower case equivalents.
                    399:                 */
                    400:                if (iflag)
                    401:                        fg->qsBc[tolower(fg->pattern[i])] = fg->patternLen - i;
                    402:        }
                    403:
                    404:        /*
                    405:         * Put pattern back to normal after pre-processing to allow for easy
                    406:         * comparisons later.
                    407:         */
                    408:        if (fg->reversedSearch)
                    409:                grep_revstr(fg->pattern, fg->patternLen);
                    410:
                    411:        return (0);
1.39    ! tedu      412: #endif
1.6       tedu      413: }
                    414:
1.26      otto      415: /*
                    416:  * Word boundaries using regular expressions are defined as the point
                    417:  * of transition from a non-word char to a word char, or vice versa.
                    418:  * This means that grep -w +a and grep -w a+ never match anything,
                    419:  * because they lack a starting or ending transition, but grep -w a+b
                    420:  * does match a line containing a+b.
                    421:  */
1.22      millert   422: #define wmatch(d, l, s, e)     \
1.26      otto      423:        ((s == 0 || !isword(d[s-1])) && (e == l || !isword(d[e])) && \
                    424:          e > s && isword(d[s]) && isword(d[e-1]))
1.22      millert   425:
1.9       millert   426: static int
1.23      millert   427: grep_search(fastgrep_t *fg, unsigned char *data, size_t dataLen, regmatch_t *pmatch)
1.6       tedu      428: {
1.39    ! tedu      429: #ifdef SMALL
        !           430:        return 0;
        !           431: #else
1.6       tedu      432:        int j;
                    433:        int rtrnVal = REG_NOMATCH;
                    434:
1.9       millert   435:        pmatch->rm_so = -1;
                    436:        pmatch->rm_eo = -1;
                    437:
1.6       tedu      438:        /* No point in going farther if we do not have enough data. */
                    439:        if (dataLen < fg->patternLen)
                    440:                return (rtrnVal);
                    441:
                    442:        /* Only try once at the beginning or ending of the line. */
                    443:        if (fg->bol || fg->eol) {
                    444:                /* Simple text comparison. */
                    445:                /* Verify data is >= pattern length before searching on it. */
                    446:                if (dataLen >= fg->patternLen) {
                    447:                        /* Determine where in data to start search at. */
                    448:                        if (fg->eol)
                    449:                                j = dataLen - fg->patternLen;
                    450:                        else
                    451:                                j = 0;
                    452:                        if (!((fg->bol && fg->eol) && (dataLen != fg->patternLen)))
1.22      millert   453:                                if (grep_cmp(fg->pattern, data + j,
                    454:                                    fg->patternLen) == -1) {
1.9       millert   455:                                        pmatch->rm_so = j;
                    456:                                        pmatch->rm_eo = j + fg->patternLen;
1.22      millert   457:                                        if (!fg->wmatch || wmatch(data, dataLen,
                    458:                                            pmatch->rm_so, pmatch->rm_eo))
                    459:                                                rtrnVal = 0;
1.9       millert   460:                                }
1.6       tedu      461:                }
                    462:        } else if (fg->reversedSearch) {
                    463:                /* Quick Search algorithm. */
1.17      millert   464:                j = dataLen;
                    465:                do {
1.6       tedu      466:                        if (grep_cmp(fg->pattern, data + j - fg->patternLen,
                    467:                            fg->patternLen) == -1) {
1.9       millert   468:                                pmatch->rm_so = j - fg->patternLen;
                    469:                                pmatch->rm_eo = j;
1.22      millert   470:                                if (!fg->wmatch || wmatch(data, dataLen,
                    471:                                    pmatch->rm_so, pmatch->rm_eo)) {
                    472:                                        rtrnVal = 0;
                    473:                                        break;
                    474:                                }
1.6       tedu      475:                        }
1.17      millert   476:                        /* Shift if within bounds, otherwise, we are done. */
                    477:                        if (j == fg->patternLen)
                    478:                                break;
                    479:                        j -= fg->qsBc[data[j - fg->patternLen - 1]];
                    480:                } while (j >= fg->patternLen);
1.6       tedu      481:        } else {
                    482:                /* Quick Search algorithm. */
                    483:                j = 0;
                    484:                do {
                    485:                        if (grep_cmp(fg->pattern, data + j, fg->patternLen) == -1) {
1.9       millert   486:                                pmatch->rm_so = j;
                    487:                                pmatch->rm_eo = j + fg->patternLen;
1.32      jaredy    488:                                if (fg->patternLen == 0 || !fg->wmatch ||
                    489:                                    wmatch(data, dataLen, pmatch->rm_so,
                    490:                                    pmatch->rm_eo)) {
1.22      millert   491:                                        rtrnVal = 0;
                    492:                                        break;
                    493:                                }
1.6       tedu      494:                        }
                    495:
                    496:                        /* Shift if within bounds, otherwise, we are done. */
                    497:                        if (j + fg->patternLen == dataLen)
                    498:                                break;
                    499:                        else
                    500:                                j += fg->qsBc[data[j + fg->patternLen]];
                    501:                } while (j <= (dataLen - fg->patternLen));
                    502:        }
                    503:
                    504:        return (rtrnVal);
1.39    ! tedu      505: #endif
1.6       tedu      506: }
                    507:
                    508:
1.1       deraadt   509: void *
                    510: grep_malloc(size_t size)
                    511: {
1.10      deraadt   512:        void    *ptr;
1.1       deraadt   513:
                    514:        if ((ptr = malloc(size)) == NULL)
1.14      millert   515:                err(2, "malloc");
1.35      deraadt   516:        return ptr;
                    517: }
                    518:
                    519: void *
                    520: grep_calloc(size_t nmemb, size_t size)
                    521: {
                    522:        void    *ptr;
                    523:
                    524:        if ((ptr = calloc(nmemb, size)) == NULL)
                    525:                err(2, "calloc");
1.1       deraadt   526:        return ptr;
                    527: }
                    528:
                    529: void *
                    530: grep_realloc(void *ptr, size_t size)
                    531: {
                    532:        if ((ptr = realloc(ptr, size)) == NULL)
1.14      millert   533:                err(2, "realloc");
1.6       tedu      534:        return ptr;
                    535: }
                    536:
1.39    ! tedu      537: #ifndef SMALL
1.6       tedu      538: /*
                    539:  * Returns:    i >= 0 on failure (position that it failed)
                    540:  *             -1 on success
                    541:  */
1.18      avsm      542: static int
1.9       millert   543: grep_cmp(const unsigned char *pattern, const unsigned char *data, size_t len)
1.6       tedu      544: {
                    545:        int i;
                    546:
                    547:        for (i = 0; i < len; i++) {
1.25      millert   548:                if (((pattern[i] == data[i]) || (!Fflag && pattern[i] == '.'))
                    549:                    || (iflag && pattern[i] == toupper(data[i])))
1.6       tedu      550:                        continue;
                    551:                return (i);
                    552:        }
                    553:
                    554:        return (-1);
                    555: }
                    556:
                    557: static void
                    558: grep_revstr(unsigned char *str, int len)
                    559: {
                    560:        int i;
                    561:        char c;
                    562:
                    563:        for (i = 0; i < len / 2; i++) {
                    564:                c = str[i];
                    565:                str[i] = str[len - i - 1];
                    566:                str[len - i - 1] = c;
                    567:        }
1.1       deraadt   568: }
1.39    ! tedu      569: #endif
1.1       deraadt   570:
                    571: void
                    572: printline(str_t *line, int sep)
                    573: {
                    574:        int n;
1.2       deraadt   575:
1.1       deraadt   576:        n = 0;
                    577:        if (!hflag) {
                    578:                fputs(line->file, stdout);
                    579:                ++n;
                    580:        }
                    581:        if (nflag) {
                    582:                if (n)
                    583:                        putchar(sep);
                    584:                printf("%d", line->line_no);
                    585:                ++n;
                    586:        }
                    587:        if (bflag) {
                    588:                if (n)
                    589:                        putchar(sep);
1.21      otto      590:                printf("%lld", (long long)line->off);
                    591:                ++n;
1.1       deraadt   592:        }
                    593:        if (n)
                    594:                putchar(sep);
                    595:        fwrite(line->dat, line->len, 1, stdout);
                    596:        putchar('\n');
                    597: }