[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.35

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