309 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			309 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /* ELLE - Copyright 1982, 1985, 1987 by Ken Harrenstien, SRI International
 | ||
|  *	This software is quasi-public; it may be used freely with
 | ||
|  *	like software, but may NOT be sold or made part of licensed
 | ||
|  *	products without permission of the author.
 | ||
|  */
 | ||
| /* EEMAKE - IMAGEN configuration functions for interfacing to "make".
 | ||
|  *	Written by (I think) Chris Ryland at IMAGEN, who also
 | ||
|  * wrote other functions scattered through ELLE.  These are either
 | ||
|  * conditionalized or are commented as being derived from the IMAGEN
 | ||
|  * configuration.
 | ||
|  *
 | ||
|  * KLH: An attempt has been made to keep these routines updated as ELLE
 | ||
|  * changed, but their workings cannot be guaranteed.
 | ||
|  */
 | ||
| 
 | ||
| 
 | ||
| /*
 | ||
|  * eemake: "make" (and other program) support
 | ||
|  *
 | ||
|  * Next-error depends on programs writing error messages of the form:
 | ||
|  *  "file", line n: message
 | ||
|  * which is a de facto standard, at least in some worlds.
 | ||
|  */
 | ||
| 
 | ||
| #include "elle.h"
 | ||
| 
 | ||
| #if !(IMAGEN)		/* Only with IMAGEN config for now */
 | ||
| f_xucmd() {}
 | ||
| f_make() {}
 | ||
| f_nxterr() {}
 | ||
| #else
 | ||
| 
 | ||
| #include <stdio.h>
 | ||
| 
 | ||
| struct buffer *exec_buf;	/* Ptr to "Execution" buffer */
 | ||
| 				/* Only external ref is from e_buff.c */
 | ||
| 
 | ||
| #define MSGLENGTH (scr_wid - 11)	/* Max length of message */
 | ||
| int fresh_make = 1;			/* Fresh Execution buffer contents */
 | ||
| chroff last_error_BOL;			/* Dot for last-error's BOL */
 | ||
| 
 | ||
| /* EFUN: "Execute Unix Command" */
 | ||
| f_xucmd()
 | ||
| {
 | ||
| 	make_or_unix_cmd(0);
 | ||
| }
 | ||
| 
 | ||
| /* EFUN: "Execute Make" */
 | ||
| f_make()
 | ||
| {
 | ||
| 	make_or_unix_cmd(1);
 | ||
| }
 | ||
| 
 | ||
| /* EFUN: "Find Next Error" */
 | ||
| f_nxterr()
 | ||
| {
 | ||
| 	register struct sbstr *sb;
 | ||
| 	register char *cp;
 | ||
| 	register int c;
 | ||
| 	char file[64], line[32];
 | ||
| #ifdef ONEWINDOW
 | ||
| 	char msg[512];
 | ||
| #endif
 | ||
| 	chroff linedot;
 | ||
| 	int lineno;
 | ||
| 	register int len;
 | ||
| 
 | ||
| 	sel_execbuf();
 | ||
| 	if (! fresh_make)
 | ||
| 	  {	e_go(last_error_BOL);
 | ||
| 		e_gonl();
 | ||
| 	  }
 | ||
| 	else
 | ||
| 	  {	fresh_make = 0;
 | ||
| 		e_gobob();
 | ||
| 		last_error_BOL = e_dot();
 | ||
| 	  }
 | ||
| 
 | ||
| 	/* Looking for `"file", line n: msg' */
 | ||
| 	if (! e_search("\", line ", 8, 0))
 | ||
| 		goto failed;
 | ||
| 	linedot = e_dot();
 | ||
| 	e_gobol();			/* Found something, get to BOL */
 | ||
| 	if (e_getc() != '"')
 | ||
| 		goto failed;		/* Insist on beginning "file" */
 | ||
| 	cp = file;			/* Pick up filename */
 | ||
| 	while ((c = e_getc()) != '"')
 | ||
| 		*cp++ = c;
 | ||
| 	*cp = 0;
 | ||
| 	e_go(linedot);			/* Back to after "line " */
 | ||
| 	cp = line;
 | ||
| 	while ((c = e_getc()) >= '0' && c <= '9')
 | ||
| 		*cp++ = c;
 | ||
| 	*cp = 0;
 | ||
| 	lineno = atoi(line);		/* Pick up line number */
 | ||
| #ifdef ONEWINDOW
 | ||
| 	cp = msg;			/* Now get rest of line to msg */
 | ||
| 	len = 0;			/* But keep length <= MSGLENGTH */
 | ||
| 	e_getc();			/* Go past purported space */
 | ||
| 	while ((c = e_getc()) != LF && c != EOF && len <= MSGLENGTH)
 | ||
| 	  {	if (c == '\t')
 | ||
| 			len = (len + 8) & ~07;
 | ||
| 		else if (c < ' ' || c > 0176)
 | ||
| 			len += 2;
 | ||
| 		else
 | ||
| 			++len;
 | ||
| 		*cp++ = c;
 | ||
| 	  }
 | ||
| 	*cp = 0;
 | ||
| 	if (len > MSGLENGTH)
 | ||
| 		strcat(msg, "...");
 | ||
| #ifdef DEBUG
 | ||
| 	say("file ");
 | ||
| 	saytoo(file);
 | ||
| 	saytoo(", line ");
 | ||
| 	saytoo(line);
 | ||
| 	saytoo(", msg: ");
 | ||
| 	sayntoo(msg);
 | ||
| #else
 | ||
| 	say(line);
 | ||
| 	saytoo(": ");
 | ||
| 	sayntoo(msg);
 | ||
| #endif /*DEBUG*/
 | ||
| #else /* -ONEWINDOW */
 | ||
| 	f_begline();			/* Get to start of line */
 | ||
| 	last_error_BOL = e_dot();	/* Remember this position */
 | ||
| 	exp_p = 1;			/* Make this the new top line */
 | ||
| 	exp = 0;
 | ||
| 	f_newwin();
 | ||
| 	upd_wind(0);
 | ||
| #endif /*ONEWINDOW*/
 | ||
| 
 | ||
| 	/* Now, visit the given file and line */
 | ||
| #ifdef ONEWINDOW	
 | ||
| #else
 | ||
| 	f_othwind();			/* To other window */
 | ||
| #endif
 | ||
| 	find_file(file);
 | ||
| 	f_gobeg();
 | ||
| 	down_line(lineno - 1);
 | ||
| #ifdef READJUST				/* NAW */
 | ||
| 	exp_p = 1;
 | ||
| 	exp = cur_win->w_ht / 4;	/* Adjust how we look at "error" */
 | ||
| 	f_newwin();
 | ||
| #endif /*READJUST*/
 | ||
| 	return;
 | ||
| 
 | ||
| failed:	ding("No more errors!");
 | ||
| 	fresh_make = 1;			/* Fake-out: pretend starting over */
 | ||
| 	return;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /* Do the "cmd" and put its output in the Execution buffer */
 | ||
| do_exec(cmd, nicely)
 | ||
| char *cmd;
 | ||
| int nicely;
 | ||
| {
 | ||
| 	register int n;
 | ||
| 	int status, res, pid, fd[2];
 | ||
| 	char nicecmd[256];
 | ||
| 	char pipebuff[512];
 | ||
| 	struct buffer *b;
 | ||
| 
 | ||
| 	b = cur_buf;
 | ||
| 	sel_execbuf();			/* Get our execution buffer up */
 | ||
| 	ed_reset();			/* Clear it out */
 | ||
| 	fresh_make = 1;
 | ||
| 	upd_wind(0);
 | ||
| 	if (nicely)
 | ||
| 		sayntoo(" ...starting up...");
 | ||
| 	else
 | ||
| 		sayntoo(" ...starting up (nasty person)...");
 | ||
| 	pipe(fd);
 | ||
| 	switch (pid = fork())
 | ||
| 	  {
 | ||
| 	case -1:
 | ||
| 		/* Fork failed, in parent */
 | ||
| 		ding("Cannot fork!?!");
 | ||
| 		break;
 | ||
| 
 | ||
| 	case 0: /* In child */
 | ||
| 		for (n = 0; n < 20; ++n)
 | ||
| 			if (n != fd[0] && n != fd[1])
 | ||
| 				close(n);
 | ||
| 		open("/dev/null", 0);	/* Give ourselves empty stdin */
 | ||
| 		dup(fd[1]);
 | ||
| 		dup(fd[1]);		/* stdout, stderr out to pipe */
 | ||
| 		close(fd[1]);		/* Close the pipe itself */
 | ||
| 		close(fd[0]);
 | ||
| 		if (nicely)
 | ||
| 		  {	strcpy(nicecmd, "nice -4 ");
 | ||
| 			strcat(nicecmd, cmd);
 | ||
| 			execl("/bin/sh", "sh", "-c", nicecmd, 0);
 | ||
| 		  }
 | ||
| 		else
 | ||
| 			execl("/bin/sh", "sh", "-c", cmd, 0);
 | ||
| 		write(1, "Cannot execute!", 15);
 | ||
| 		_exit(-1);
 | ||
| 		break;
 | ||
| 
 | ||
| 	default:
 | ||
| 		/* Parent */
 | ||
| 		close(fd[1]);		/* Close the output direction */
 | ||
| 		while ((n = read(fd[0], pipebuff, sizeof(pipebuff))) > 0)
 | ||
| 		  {	ed_nsins(pipebuff, n);
 | ||
| 			upd_wind(0);
 | ||
| 			saynow("Chugging along...");
 | ||
| 		  }
 | ||
| 		close(fd[0]);
 | ||
| 		while ((res = wait(&status)) != pid && res != -1)
 | ||
| 			;		/* Wait for this fork to die */
 | ||
| 		f_bufnotmod();		/* Buffer is fresh */
 | ||
| 		saynow("Done!");
 | ||
| 		break;
 | ||
| 	  }
 | ||
| 	f_othwind();			/* Back to other window */
 | ||
| 	chg_buf(b);			/* Back to original buffer */
 | ||
| }
 | ||
| 
 | ||
| char last_make_cmd[256];		/* Last Unix/make command */
 | ||
| int have_last_make_cmd = 0;
 | ||
| 
 | ||
| make_or_unix_cmd(domake)
 | ||
| int domake;
 | ||
| {
 | ||
| #if APOLLO
 | ||
| 	register int nicely = exp == 16;	/* modification for apollo */
 | ||
| #else
 | ||
| 	register int nicely = exp != 16;
 | ||
| #endif /*-APOLLO*/
 | ||
| 	register char *reply, *cmd = 0;
 | ||
| 
 | ||
| 	if (domake)			/* If "make"-style, */
 | ||
| 	  {	int savp = exp_p;
 | ||
| 		exp_p = 1;
 | ||
| 		f_savefiles();		/*  write modified files quietly */
 | ||
| 		exp_p = savp;
 | ||
| 	  }
 | ||
| 	if (exp_p || ! domake)
 | ||
| 	  {		/* Arg given make, or Unix command */
 | ||
| 		reply = ask((! domake) ? "Unix command: " : "Command: ");
 | ||
| 		if (! reply)
 | ||
| 			return;
 | ||
| 		if (*reply == 0)
 | ||
| 		  {	if (have_last_make_cmd)
 | ||
| 				cmd = &last_make_cmd[0];
 | ||
| 			else
 | ||
| 			  {	chkfree(reply);
 | ||
| 				ding("No previous command!");
 | ||
| 				return;
 | ||
| 			  }
 | ||
| 		  }
 | ||
| 		else
 | ||
| 			cmd = reply;
 | ||
| 		if (cmd != &last_make_cmd[0])	/* Update last command */
 | ||
| 			strcpy(last_make_cmd, cmd);
 | ||
| 		have_last_make_cmd = 1;
 | ||
| 		say("Command: ");
 | ||
| 		sayntoo(cmd);
 | ||
| 		do_exec(cmd, nicely);
 | ||
| 		chkfree(reply);
 | ||
| 	  }
 | ||
| 	else if (have_last_make_cmd)
 | ||
| 	  {	say("Command: ");
 | ||
| 		sayntoo(last_make_cmd);
 | ||
| 		do_exec(last_make_cmd, nicely);
 | ||
| 	  }
 | ||
| 	else
 | ||
| 	  {	saynow("Command: make");
 | ||
| 		do_exec("make", nicely);
 | ||
| 	  }
 | ||
| }
 | ||
| 
 | ||
| sel_execbuf()
 | ||
| {	if(!exec_buf)
 | ||
| 	  {	/* Make execution buffer; don't let anyone kill it */
 | ||
| 		exec_buf = make_buf("Execution");
 | ||
| 		exec_buf->b_flags |= B_PERMANENT;
 | ||
| 	  }
 | ||
| 	popto_buf(exec_buf);
 | ||
| }
 | ||
| 
 | ||
| /* Utility: pop the given buffer to a window, getting into 2-window mode */
 | ||
| popto_buf(b)
 | ||
| register struct buffer *b;
 | ||
| {
 | ||
| 	/* See if we already have this buffer in a visible window */
 | ||
| 	if (b == cur_win->w_buf)
 | ||
| 	  {	if (oth_win == 0)
 | ||
| 		  {	f_2winds();
 | ||
| 			f_othwind();		/* Get back to our window */
 | ||
| 		  }
 | ||
| 	  }
 | ||
| 	else if (oth_win != 0 && b == oth_win->w_buf)
 | ||
| 		f_othwind();
 | ||
| 	else if (oth_win == 0)
 | ||
| 	  {		/* One window mode */
 | ||
| 		f_2winds();			/* Get two, get into second */
 | ||
| 		sel_buf(b);			/* Select our new buffer */
 | ||
| 	  }
 | ||
| 	else
 | ||
| 	  {	f_othwind();			/* Get to other window */
 | ||
| 		sel_buf(b);			/*  and select our buffer */
 | ||
| 	  }
 | ||
| }
 | ||
| 
 | ||
| #endif /*IMAGEN*/
 | 
