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

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