/* 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 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*/