Edit

IABSD.fr/src/usr.bin/mg/grep.c

Branch :

  • Show log

    Commit

  • Author : lum
    Date : 2019-07-11 18:20:18
    Hash : f8588f90
    Message : Allow functions that have 1 or more parameters receive and process multiple arguments when evaluated in a startup file or via one of the 'eval' commands. This diff does treat the '(' and ')' chars differently during evaluation than previously, in-so-far as they are not ignored if they are at the end or start of a line now. However, even though these characters are not ignored, this diff should not change the behaviour of an extant .mg file, with '(' and ')' chars at the end and start of a line. This situation is accomodated for in this diff (with limited testing though).

  • usr.bin/mg/grep.c
  • /*	$OpenBSD: grep.c,v 1.48 2019/07/11 18:20:18 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] == '\n')
    			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);
    }