Changeset View
Changeset View
Standalone View
Standalone View
contrib/mg/grep.c
- This file was added.
/* $OpenBSD: grep.c,v 1.49 2021/03/01 10:51:14 lum Exp $ */ | |||||
/* This file is in the public domain */ | |||||
#include <sys/queue.h> | |||||
#include <sys/types.h> | |||||
#include <sys/wait.h> | |||||
#include <ctype.h> | |||||
#include <limits.h> | |||||
#include <signal.h> | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <time.h> | |||||
#include <unistd.h> | |||||
#include "def.h" | |||||
#include "kbd.h" | |||||
#include "funmap.h" | |||||
int globalwd = FALSE; | |||||
static int compile_goto_error(int, int); | |||||
int next_error(int, int); | |||||
static int grep(int, int); | |||||
static int gid(int, int); | |||||
static struct buffer *compile_mode(const char *, const char *); | |||||
void grep_init(void); | |||||
static char compile_last_command[NFILEN] = "make "; | |||||
/* | |||||
* Hints for next-error | |||||
* | |||||
* XXX - need some kind of callback to find out when those get killed. | |||||
*/ | |||||
struct mgwin *compile_win; | |||||
struct buffer *compile_buffer; | |||||
static PF compile_pf[] = { | |||||
compile_goto_error | |||||
}; | |||||
static struct KEYMAPE (1) compilemap = { | |||||
1, | |||||
1, | |||||
rescan, | |||||
{ | |||||
{ CCHR('M'), CCHR('M'), compile_pf, NULL } | |||||
} | |||||
}; | |||||
void | |||||
grep_init(void) | |||||
{ | |||||
funmap_add(compile_goto_error, "compile-goto-error", 0); | |||||
funmap_add(next_error, "next-error", 0); | |||||
funmap_add(grep, "grep", 1); | |||||
funmap_add(compile, "compile", 0); | |||||
funmap_add(gid, "gid", 1); | |||||
maps_add((KEYMAP *)&compilemap, "compile"); | |||||
} | |||||
/* ARGSUSED */ | |||||
static int | |||||
grep(int f, int n) | |||||
{ | |||||
char cprompt[NFILEN], *bufp; | |||||
struct buffer *bp; | |||||
struct mgwin *wp; | |||||
(void)strlcpy(cprompt, "grep -n ", sizeof(cprompt)); | |||||
if ((bufp = eread("Run grep: ", cprompt, NFILEN, | |||||
EFDEF | EFNEW | EFCR)) == NULL) | |||||
return (ABORT); | |||||
else if (bufp[0] == '\0') | |||||
return (FALSE); | |||||
if (strlcat(cprompt, " /dev/null", sizeof(cprompt)) >= sizeof(cprompt)) | |||||
return (FALSE); | |||||
if ((bp = compile_mode("*grep*", cprompt)) == NULL) | |||||
return (FALSE); | |||||
if ((wp = popbuf(bp, WNONE)) == NULL) | |||||
return (FALSE); | |||||
curbp = bp; | |||||
compile_win = curwp = wp; | |||||
return (TRUE); | |||||
} | |||||
/* ARGSUSED */ | |||||
int | |||||
compile(int f, int n) | |||||
{ | |||||
char cprompt[NFILEN], *bufp; | |||||
struct buffer *bp; | |||||
struct mgwin *wp; | |||||
(void)strlcpy(cprompt, compile_last_command, sizeof(cprompt)); | |||||
if ((bufp = eread("Compile command: ", cprompt, NFILEN, | |||||
EFDEF | EFNEW | EFCR)) == NULL) | |||||
return (ABORT); | |||||
else if (bufp[0] == '\0') | |||||
return (FALSE); | |||||
if (savebuffers(f, n) == ABORT) | |||||
return (ABORT); | |||||
(void)strlcpy(compile_last_command, bufp, sizeof(compile_last_command)); | |||||
if ((bp = compile_mode("*compile*", cprompt)) == NULL) | |||||
return (FALSE); | |||||
if ((wp = popbuf(bp, WNONE)) == NULL) | |||||
return (FALSE); | |||||
curbp = bp; | |||||
compile_win = curwp = wp; | |||||
gotoline(FFARG, 0); | |||||
return (TRUE); | |||||
} | |||||
/* id-utils foo. */ | |||||
/* ARGSUSED */ | |||||
static int | |||||
gid(int f, int n) | |||||
{ | |||||
char command[NFILEN]; | |||||
char cprompt[NFILEN], *bufp; | |||||
int c; | |||||
struct buffer *bp; | |||||
struct mgwin *wp; | |||||
int i, j, len; | |||||
/* catch ([^\s(){}]+)[\s(){}]* */ | |||||
i = curwp->w_doto; | |||||
/* Skip backwards over delimiters we are currently on */ | |||||
while (i > 0) { | |||||
c = lgetc(curwp->w_dotp, i); | |||||
if (isalnum(c) || c == '_') | |||||
break; | |||||
i--; | |||||
} | |||||
/* Skip the symbol itself */ | |||||
for (; i > 0; i--) { | |||||
c = lgetc(curwp->w_dotp, i - 1); | |||||
if (!isalnum(c) && c != '_') | |||||
break; | |||||
} | |||||
/* Fill the symbol in cprompt[] */ | |||||
for (j = 0; j < sizeof(cprompt) - 1 && i < llength(curwp->w_dotp); | |||||
j++, i++) { | |||||
c = lgetc(curwp->w_dotp, i); | |||||
if (!isalnum(c) && c != '_') | |||||
break; | |||||
cprompt[j] = c; | |||||
} | |||||
cprompt[j] = '\0'; | |||||
if ((bufp = eread("Run gid (with args): ", cprompt, NFILEN, | |||||
(j ? EFDEF : 0) | EFNEW | EFCR)) == NULL) | |||||
return (ABORT); | |||||
else if (bufp[0] == '\0') | |||||
return (FALSE); | |||||
len = snprintf(command, sizeof(command), "gid %s", cprompt); | |||||
if (len < 0 || len >= sizeof(command)) | |||||
return (FALSE); | |||||
if ((bp = compile_mode("*gid*", command)) == NULL) | |||||
return (FALSE); | |||||
if ((wp = popbuf(bp, WNONE)) == NULL) | |||||
return (FALSE); | |||||
curbp = bp; | |||||
compile_win = curwp = wp; | |||||
return (TRUE); | |||||
} | |||||
struct buffer * | |||||
compile_mode(const char *name, const char *command) | |||||
{ | |||||
struct buffer *bp; | |||||
FILE *fpipe; | |||||
char *buf; | |||||
size_t sz; | |||||
ssize_t len; | |||||
int ret, n, status; | |||||
char cwd[NFILEN], qcmd[NFILEN]; | |||||
char timestr[NTIME]; | |||||
time_t t; | |||||
buf = NULL; | |||||
sz = 0; | |||||
n = snprintf(qcmd, sizeof(qcmd), "%s 2>&1", command); | |||||
if (n < 0 || n >= sizeof(qcmd)) | |||||
return (NULL); | |||||
bp = bfind(name, TRUE); | |||||
if (bclear(bp) != TRUE) | |||||
return (NULL); | |||||
if (getbufcwd(bp->b_cwd, sizeof(bp->b_cwd)) != TRUE) | |||||
return (NULL); | |||||
addlinef(bp, "cd %s", bp->b_cwd); | |||||
addline(bp, qcmd); | |||||
addline(bp, ""); | |||||
if (getcwd(cwd, sizeof(cwd)) == NULL) | |||||
panic("Can't get current directory!"); | |||||
if (chdir(bp->b_cwd) == -1) { | |||||
dobeep(); | |||||
ewprintf("Can't change dir to %s", bp->b_cwd); | |||||
return (NULL); | |||||
} | |||||
if ((fpipe = popen(qcmd, "r")) == NULL) { | |||||
dobeep(); | |||||
ewprintf("Problem opening pipe"); | |||||
return (NULL); | |||||
} | |||||
while ((len = getline(&buf, &sz, fpipe)) != -1) { | |||||
if (buf[len - 1] == *bp->b_nlchr) | |||||
buf[len - 1] = '\0'; | |||||
addline(bp, buf); | |||||
} | |||||
free(buf); | |||||
if (ferror(fpipe)) | |||||
ewprintf("Problem reading pipe"); | |||||
ret = pclose(fpipe); | |||||
t = time(NULL); | |||||
strftime(timestr, sizeof(timestr), "%a %b %e %T %Y", localtime(&t)); | |||||
addline(bp, ""); | |||||
if (WIFEXITED(ret)) { | |||||
status = WEXITSTATUS(ret); | |||||
if (status == 0) | |||||
addlinef(bp, "Command finished at %s", timestr); | |||||
else | |||||
addlinef(bp, "Command exited abnormally with code %d " | |||||
"at %s", status, timestr); | |||||
} else | |||||
addlinef(bp, "Subshell killed by signal %d at %s", | |||||
WTERMSIG(ret), timestr); | |||||
bp->b_dotp = bfirstlp(bp); | |||||
bp->b_modes[0] = name_mode("fundamental"); | |||||
bp->b_modes[1] = name_mode("compile"); | |||||
bp->b_nmodes = 1; | |||||
compile_buffer = bp; | |||||
if (chdir(cwd) == -1) { | |||||
dobeep(); | |||||
ewprintf("Can't change dir back to %s", cwd); | |||||
return (NULL); | |||||
} | |||||
return (bp); | |||||
} | |||||
/* ARGSUSED */ | |||||
static int | |||||
compile_goto_error(int f, int n) | |||||
{ | |||||
struct buffer *bp; | |||||
struct mgwin *wp; | |||||
char *fname, *line, *lp, *ln; | |||||
int lineno; | |||||
char *adjf, path[NFILEN]; | |||||
const char *errstr; | |||||
struct line *last; | |||||
compile_win = curwp; | |||||
compile_buffer = curbp; | |||||
last = blastlp(compile_buffer); | |||||
retry: | |||||
/* last line is compilation result */ | |||||
if (curwp->w_dotp == last) | |||||
return (FALSE); | |||||
if ((line = linetostr(curwp->w_dotp)) == NULL) | |||||
return (FALSE); | |||||
lp = line; | |||||
if ((fname = strsep(&lp, ":")) == NULL || *fname == '\0') | |||||
goto fail; | |||||
if ((ln = strsep(&lp, ":")) == NULL || *ln == '\0') | |||||
goto fail; | |||||
lineno = (int)strtonum(ln, INT_MIN, INT_MAX, &errstr); | |||||
if (errstr) | |||||
goto fail; | |||||
if (fname && fname[0] != '/') { | |||||
if (getbufcwd(path, sizeof(path)) == FALSE) | |||||
goto fail; | |||||
if (strlcat(path, fname, sizeof(path)) >= sizeof(path)) | |||||
goto fail; | |||||
adjf = path; | |||||
} else { | |||||
adjf = adjustname(fname, TRUE); | |||||
} | |||||
free(line); | |||||
if (adjf == NULL) | |||||
return (FALSE); | |||||
if ((bp = findbuffer(adjf)) == NULL) | |||||
return (FALSE); | |||||
if ((wp = popbuf(bp, WNONE)) == NULL) | |||||
return (FALSE); | |||||
curbp = bp; | |||||
curwp = wp; | |||||
if (bp->b_fname[0] == '\0') | |||||
readin(adjf); | |||||
gotoline(FFARG, lineno); | |||||
return (TRUE); | |||||
fail: | |||||
free(line); | |||||
if (curwp->w_dotp != blastlp(curbp)) { | |||||
curwp->w_dotp = lforw(curwp->w_dotp); | |||||
curwp->w_rflag |= WFMOVE; | |||||
goto retry; | |||||
} | |||||
dobeep(); | |||||
ewprintf("No more hits"); | |||||
return (FALSE); | |||||
} | |||||
/* ARGSUSED */ | |||||
int | |||||
next_error(int f, int n) | |||||
{ | |||||
if (compile_win == NULL || compile_buffer == NULL) { | |||||
dobeep(); | |||||
ewprintf("No compilation active"); | |||||
return (FALSE); | |||||
} | |||||
curwp = compile_win; | |||||
curbp = compile_buffer; | |||||
if (curwp->w_dotp == blastlp(curbp)) { | |||||
dobeep(); | |||||
ewprintf("No more hits"); | |||||
return (FALSE); | |||||
} | |||||
curwp->w_dotp = lforw(curwp->w_dotp); | |||||
curwp->w_rflag |= WFMOVE; | |||||
return (compile_goto_error(f, n)); | |||||
} | |||||
/* | |||||
* Since we don't have variables (we probably should) these are command | |||||
* processors for changing the values of mode flags. | |||||
*/ | |||||
/* ARGSUSED */ | |||||
int | |||||
globalwdtoggle(int f, int n) | |||||
{ | |||||
if (f & FFARG) | |||||
globalwd = n > 0; | |||||
else | |||||
globalwd = !globalwd; | |||||
sgarbf = TRUE; | |||||
return (TRUE); | |||||
} |