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

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