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

Annotation of src/usr.bin/mg/grep.c, Revision 1.34

1.34    ! kjell       1: /*     $OpenBSD: grep.c,v 1.33 2006/11/19 16:51:19 deraadt Exp $       */
1.1       art         2: /*
1.18      kjell       3:  * Copyright (c) 2001 Artur Grabowski <art@openbsd.org>.
                      4:  * Copyright (c) 2005 Kjell Wooding <kjell@openbsd.org>.
                      5:  * All rights reserved.
1.1       art         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 ``AS IS'' AND ANY EXPRESS OR
                     17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     18:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     19:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     20:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     21:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     22:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     23:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     24:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     25:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     26:  */
                     27:
                     28: #include "def.h"
                     29: #include "kbd.h"
                     30: #include "funmap.h"
                     31:
1.18      kjell      32: #include <sys/types.h>
1.11      vincent    33: #include <ctype.h>
1.18      kjell      34: #include <libgen.h>
                     35: #include <time.h>
1.11      vincent    36:
1.34    ! kjell      37: int     globalwd = FALSE;
1.13      db         38: static int      compile_goto_error(int, int);
1.17      kjell      39: int             next_error(int, int);
1.13      db         40: static int      grep(int, int);
                     41: static int      compile(int, int);
                     42: static int      gid(int, int);
1.28      kjell      43: static struct buffer   *compile_mode(const char *, const char *);
1.25      kjell      44: static int      xlint(int, int);
1.1       art        45: void grep_init(void);
                     46:
1.8       vincent    47: static char compile_last_command[NFILEN] = "make ";
                     48:
1.1       art        49: /*
                     50:  * Hints for next-error
                     51:  *
                     52:  * XXX - need some kind of callback to find out when those get killed.
                     53:  */
1.24      deraadt    54: struct mgwin   *compile_win;
                     55: struct buffer  *compile_buffer;
1.1       art        56:
                     57: static PF compile_pf[] = {
1.13      db         58:        compile_goto_error
1.1       art        59: };
                     60:
                     61: static struct KEYMAPE (1 + IMAPEXT) compilemap = {
                     62:        1,
                     63:        1 + IMAPEXT,
                     64:        rescan,
                     65:        {
1.13      db         66:                { CCHR('M'), CCHR('M'), compile_pf, NULL }
1.1       art        67:        }
                     68: };
                     69:
                     70: void
                     71: grep_init(void)
                     72: {
                     73:        funmap_add(compile_goto_error, "compile-goto-error");
                     74:        funmap_add(next_error, "next-error");
                     75:        funmap_add(grep, "grep");
1.25      kjell      76:        funmap_add(xlint, "lint");
1.1       art        77:        funmap_add(compile, "compile");
                     78:        funmap_add(gid, "gid");
                     79:        maps_add((KEYMAP *)&compilemap, "compile");
                     80: }
                     81:
1.20      kjell      82: /* ARGSUSED */
1.1       art        83: static int
                     84: grep(int f, int n)
                     85: {
1.25      kjell      86:        char     cprompt[NFILEN], *bufp;
1.24      deraadt    87:        struct buffer   *bp;
                     88:        struct mgwin    *wp;
1.1       art        89:
1.25      kjell      90:        (void)strlcpy(cprompt, "grep -n ", sizeof(cprompt));
                     91:        if ((bufp = eread("Run grep: ", cprompt, NFILEN,
1.16      kjell      92:            EFDEF | EFNEW | EFCR)) == NULL)
1.13      db         93:                return (ABORT);
1.16      kjell      94:        else if (bufp[0] == '\0')
                     95:                return (FALSE);
1.29      kjell      96:        if (strlcat(cprompt, " /dev/null", sizeof(cprompt)) >= sizeof(cprompt))
                     97:                return (FALSE);
1.1       art        98:
1.29      kjell      99:        if ((bp = compile_mode("*grep*", cprompt)) == NULL)
1.13      db        100:                return (FALSE);
1.1       art       101:        if ((wp = popbuf(bp)) == NULL)
1.13      db        102:                return (FALSE);
1.1       art       103:        curbp = bp;
                    104:        compile_win = curwp = wp;
1.13      db        105:        return (TRUE);
1.1       art       106: }
                    107:
1.20      kjell     108: /* ARGSUSED */
1.1       art       109: static int
1.25      kjell     110: xlint(int f, int n)
                    111: {
                    112:        char     cprompt[NFILEN], *bufp;
                    113:        struct buffer   *bp;
                    114:        struct mgwin    *wp;
                    115:
                    116:        (void)strlcpy(cprompt, "make lint ", sizeof(cprompt));
                    117:        if ((bufp = eread("Run lint: ", cprompt, NFILEN,
                    118:            EFDEF | EFNEW | EFCR)) == NULL)
                    119:                return (ABORT);
                    120:        else if (bufp[0] == '\0')
                    121:                return (FALSE);
                    122:
1.29      kjell     123:        if ((bp = compile_mode("*lint*", cprompt)) == NULL)
1.25      kjell     124:                return (FALSE);
                    125:        if ((wp = popbuf(bp)) == NULL)
                    126:                return (FALSE);
                    127:        curbp = bp;
                    128:        compile_win = curwp = wp;
                    129:        return (TRUE);
                    130: }
                    131:
                    132: /* ARGSUSED */
                    133: static int
1.1       art       134: compile(int f, int n)
                    135: {
1.25      kjell     136:        char     cprompt[NFILEN], *bufp;
1.24      deraadt   137:        struct buffer   *bp;
                    138:        struct mgwin    *wp;
1.1       art       139:
1.25      kjell     140:        (void)strlcpy(cprompt, compile_last_command, sizeof(cprompt));
                    141:        if ((bufp = eread("Compile command: ", cprompt, NFILEN,
1.16      kjell     142:            EFDEF | EFNEW | EFCR)) == NULL)
1.14      jason     143:                return (ABORT);
1.16      kjell     144:        else if (bufp[0] == '\0')
                    145:                return (FALSE);
1.14      jason     146:        if (savebuffers(f, n) == ABORT)
1.13      db        147:                return (ABORT);
                    148:        (void)strlcpy(compile_last_command, bufp, sizeof(compile_last_command));
1.1       art       149:
1.29      kjell     150:        if ((bp = compile_mode("*compile*", cprompt)) == NULL)
1.13      db        151:                return (FALSE);
1.1       art       152:        if ((wp = popbuf(bp)) == NULL)
1.13      db        153:                return (FALSE);
1.1       art       154:        curbp = bp;
                    155:        compile_win = curwp = wp;
1.27      kjell     156:        gotoline(FFARG, 0);
1.13      db        157:        return (TRUE);
1.1       art       158: }
                    159:
                    160: /* id-utils foo. */
1.20      kjell     161: /* ARGSUSED */
1.1       art       162: static int
                    163: gid(int f, int n)
                    164: {
1.29      kjell     165:        char     command[NFILEN];
1.25      kjell     166:        char     cprompt[NFILEN], c, *bufp;
1.24      deraadt   167:        struct buffer   *bp;
                    168:        struct mgwin    *wp;
1.29      kjell     169:        int      i, j, len;
1.1       art       170:
1.11      vincent   171:        /* catch ([^\s(){}]+)[\s(){}]* */
                    172:
                    173:        i = curwp->w_doto;
1.15      cloder    174:        /* Skip backwards over delimiters we are currently on */
                    175:        while (i > 0) {
                    176:                c = lgetc(curwp->w_dotp, i);
                    177:                if (isalnum(c) || c == '_')
                    178:                        break;
                    179:
1.11      vincent   180:                i--;
1.15      cloder    181:        }
                    182:
1.11      vincent   183:        /* Skip the symbol itself */
                    184:        for (; i > 0; i--) {
                    185:                c = lgetc(curwp->w_dotp, i - 1);
1.15      cloder    186:                if (!isalnum(c) && c != '_')
1.11      vincent   187:                        break;
                    188:        }
1.25      kjell     189:        /* Fill the symbol in cprompt[] */
                    190:        for (j = 0; j < sizeof(cprompt) - 1 && i < llength(curwp->w_dotp);
1.11      vincent   191:            j++, i++) {
                    192:                c = lgetc(curwp->w_dotp, i);
1.15      cloder    193:                if (!isalnum(c) && c != '_')
1.11      vincent   194:                        break;
1.25      kjell     195:                cprompt[j] = c;
1.11      vincent   196:        }
1.25      kjell     197:        cprompt[j] = '\0';
1.11      vincent   198:
1.25      kjell     199:        if ((bufp = eread("Run gid (with args): ", cprompt, NFILEN,
1.16      kjell     200:            (j ? EFDEF : 0) | EFNEW | EFCR)) == NULL)
1.13      db        201:                return (ABORT);
1.16      kjell     202:        else if (bufp[0] == '\0')
                    203:                return (FALSE);
1.29      kjell     204:        len = snprintf(command, sizeof(command), "gid %s", cprompt);
                    205:        if (len < 0 || len >= sizeof(command))
                    206:                return (FALSE);
1.1       art       207:
1.28      kjell     208:        if ((bp = compile_mode("*gid*", command)) == NULL)
1.13      db        209:                return (FALSE);
1.1       art       210:        if ((wp = popbuf(bp)) == NULL)
1.13      db        211:                return (FALSE);
1.1       art       212:        curbp = bp;
                    213:        compile_win = curwp = wp;
1.13      db        214:        return (TRUE);
1.1       art       215: }
                    216:
1.24      deraadt   217: struct buffer *
1.28      kjell     218: compile_mode(const char *name, const char *command)
1.1       art       219: {
1.24      deraadt   220:        struct buffer   *bp;
1.26      kjell     221:        FILE    *fpipe;
1.13      db        222:        char    *buf;
                    223:        size_t   len;
1.29      kjell     224:        int      ret, n;
                    225:        char     cwd[NFILEN], qcmd[NFILEN];
1.18      kjell     226:        char     timestr[NTIME];
                    227:        time_t   t;
1.1       art       228:
1.29      kjell     229:        n = snprintf(qcmd, sizeof(qcmd), "%s 2>&1", command);
                    230:        if (n < 0 || n >= sizeof(qcmd))
                    231:                return (NULL);
                    232:
1.1       art       233:        bp = bfind(name, TRUE);
                    234:        if (bclear(bp) != TRUE)
1.13      db        235:                return (NULL);
1.1       art       236:
1.28      kjell     237:        if (getbufcwd(bp->b_cwd, sizeof(bp->b_cwd)) != TRUE)
                    238:                return (NULL);
                    239:        addlinef(bp, "cd %s", bp->b_cwd);
1.29      kjell     240:        addline(bp, qcmd);
1.1       art       241:        addline(bp, "");
                    242:
1.23      deraadt   243:        if (getcwd(cwd, sizeof(cwd)) == NULL)
1.18      kjell     244:                panic("Can't get current directory!");
1.28      kjell     245:        if (chdir(bp->b_cwd) == -1) {
                    246:                ewprintf("Can't change dir to %s", bp->b_cwd);
1.18      kjell     247:                return (NULL);
1.19      deraadt   248:        }
1.29      kjell     249:        if ((fpipe = popen(qcmd, "r")) == NULL) {
1.1       art       250:                ewprintf("Problem opening pipe");
1.13      db        251:                return (NULL);
1.1       art       252:        }
                    253:        /*
                    254:         * We know that our commands are nice and the last line will end with
                    255:         * a \n, so we don't need to try to deal with the last line problem
                    256:         * in fgetln.
                    257:         */
1.26      kjell     258:        while ((buf = fgetln(fpipe, &len)) != NULL) {
1.1       art       259:                buf[len - 1] = '\0';
                    260:                addline(bp, buf);
                    261:        }
1.26      kjell     262:        ret = pclose(fpipe);
1.18      kjell     263:        t = time(NULL);
                    264:        strftime(timestr, sizeof(timestr), "%a %b %e %T %Y", localtime(&t));
1.1       art       265:        addline(bp, "");
1.18      kjell     266:        if (ret != 0)
                    267:                addlinef(bp, "Command exited abnormally with code %d"
                    268:                    " at %s", ret, timestr);
                    269:        else
                    270:                addlinef(bp, "Command finished at %s", timestr);
                    271:
1.32      kjell     272:        bp->b_dotp = bfirstlp(bp);
1.1       art       273:        bp->b_modes[0] = name_mode("fundamental");
                    274:        bp->b_modes[1] = name_mode("compile");
                    275:        bp->b_nmodes = 1;
                    276:
                    277:        compile_buffer = bp;
                    278:
1.18      kjell     279:        if (chdir(cwd) == -1) {
                    280:                ewprintf("Can't change dir back to %s", cwd);
                    281:                return (NULL);
1.19      deraadt   282:        }
1.13      db        283:        return (bp);
1.1       art       284: }
                    285:
1.20      kjell     286: /* ARGSUSED */
1.1       art       287: static int
                    288: compile_goto_error(int f, int n)
                    289: {
1.24      deraadt   290:        struct buffer   *bp;
                    291:        struct mgwin    *wp;
1.21      kjell     292:        char    *fname, *line, *lp, *ln;
1.29      kjell     293:        int      lineno;
1.28      kjell     294:        char    *adjf, path[NFILEN];
1.21      kjell     295:        const char *errstr;
1.24      deraadt   296:        struct line     *last;
1.1       art       297:
                    298:        compile_win = curwp;
                    299:        compile_buffer = curbp;
1.32      kjell     300:        last = blastlp(compile_buffer);
1.22      deraadt   301:
1.21      kjell     302:  retry:
                    303:        /* last line is compilation result */
                    304:        if (curwp->w_dotp == last)
                    305:                return (FALSE);
1.33      deraadt   306:
1.29      kjell     307:        if ((line = linetostr(curwp->w_dotp)) == NULL)
1.13      db        308:                return (FALSE);
1.1       art       309:        lp = line;
1.21      kjell     310:        if ((fname = strsep(&lp, ":")) == NULL || *fname == '\0')
1.1       art       311:                goto fail;
1.21      kjell     312:        if ((ln = strsep(&lp, ":")) == NULL || *ln == '\0')
1.1       art       313:                goto fail;
1.24      deraadt   314:        lineno = (int)strtonum(ln, INT_MIN, INT_MAX, &errstr);
1.21      kjell     315:        if (errstr)
1.1       art       316:                goto fail;
1.33      deraadt   317:
1.28      kjell     318:        if (fname && fname[0] != '/') {
1.34    ! kjell     319:                if (getbufcwd(path, sizeof(path)) == FALSE)
        !           320:                        goto fail;
1.28      kjell     321:                if (strlcat(path, fname, sizeof(path)) >= sizeof(path))
                    322:                        goto fail;
                    323:                adjf = path;
                    324:        } else {
1.30      jason     325:                adjf = adjustname(fname, TRUE);
1.28      kjell     326:        }
1.1       art       327:        free(line);
                    328:
1.7       vincent   329:        if (adjf == NULL)
                    330:                return (FALSE);
1.10      vincent   331:
1.1       art       332:        if ((bp = findbuffer(adjf)) == NULL)
1.13      db        333:                return (FALSE);
1.1       art       334:        if ((wp = popbuf(bp)) == NULL)
1.13      db        335:                return (FALSE);
1.1       art       336:        curbp = bp;
                    337:        curwp = wp;
1.27      kjell     338:        if (bp->b_fname[0] == '\0')
1.1       art       339:                readin(adjf);
                    340:        gotoline(FFARG, lineno);
1.13      db        341:        return (TRUE);
1.1       art       342: fail:
1.3       deraadt   343:        free(line);
1.32      kjell     344:        if (curwp->w_dotp != blastlp(curbp)) {
1.1       art       345:                curwp->w_dotp = lforw(curwp->w_dotp);
                    346:                curwp->w_flag |= WFMOVE;
                    347:                goto retry;
                    348:        }
                    349:        ewprintf("No more hits");
1.13      db        350:        return (FALSE);
1.1       art       351: }
                    352:
1.20      kjell     353: /* ARGSUSED */
1.17      kjell     354: int
1.1       art       355: next_error(int f, int n)
                    356: {
                    357:        if (compile_win == NULL || compile_buffer == NULL) {
                    358:                ewprintf("No compilation active");
1.13      db        359:                return (FALSE);
1.1       art       360:        }
                    361:        curwp = compile_win;
                    362:        curbp = compile_buffer;
1.32      kjell     363:        if (curwp->w_dotp == blastlp(curbp)) {
1.1       art       364:                ewprintf("No more hits");
1.13      db        365:                return (FALSE);
1.1       art       366:        }
                    367:        curwp->w_dotp = lforw(curwp->w_dotp);
                    368:        curwp->w_flag |= WFMOVE;
                    369:
1.13      db        370:        return (compile_goto_error(f, n));
1.34    ! kjell     371: }
        !           372:
        !           373: /*
        !           374:  * Since we don't have variables (we probably should) these are command
        !           375:  * processors for changing the values of mode flags.
        !           376:  */
        !           377: /* ARGSUSED */
        !           378: int
        !           379: globalwdtoggle(int f, int n)
        !           380: {
        !           381:        if (f & FFARG)
        !           382:                globalwd = n > 0;
        !           383:        else
        !           384:                globalwd = !globalwd;
        !           385:
        !           386:        sgarbf = TRUE;
        !           387:
        !           388:        return (TRUE);
1.1       art       389: }