309 lines
6.9 KiB
C
309 lines
6.9 KiB
C
|
/* 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*/
|