[9] | 1 | /* ELLE - Copyright 1982, 1985, 1987 by Ken Harrenstien, SRI International
|
---|
| 2 | * This software is quasi-public; it may be used freely with
|
---|
| 3 | * like software, but may NOT be sold or made part of licensed
|
---|
| 4 | * products without permission of the author.
|
---|
| 5 | */
|
---|
| 6 | /* EEMAKE - IMAGEN configuration functions for interfacing to "make".
|
---|
| 7 | * Written by (I think) Chris Ryland at IMAGEN, who also
|
---|
| 8 | * wrote other functions scattered through ELLE. These are either
|
---|
| 9 | * conditionalized or are commented as being derived from the IMAGEN
|
---|
| 10 | * configuration.
|
---|
| 11 | *
|
---|
| 12 | * KLH: An attempt has been made to keep these routines updated as ELLE
|
---|
| 13 | * changed, but their workings cannot be guaranteed.
|
---|
| 14 | */
|
---|
| 15 |
|
---|
| 16 |
|
---|
| 17 | /*
|
---|
| 18 | * eemake: "make" (and other program) support
|
---|
| 19 | *
|
---|
| 20 | * Next-error depends on programs writing error messages of the form:
|
---|
| 21 | * "file", line n: message
|
---|
| 22 | * which is a de facto standard, at least in some worlds.
|
---|
| 23 | */
|
---|
| 24 |
|
---|
| 25 | #include "elle.h"
|
---|
| 26 |
|
---|
| 27 | #if !(IMAGEN) /* Only with IMAGEN config for now */
|
---|
| 28 | f_xucmd() {}
|
---|
| 29 | f_make() {}
|
---|
| 30 | f_nxterr() {}
|
---|
| 31 | #else
|
---|
| 32 |
|
---|
| 33 | #include <stdio.h>
|
---|
| 34 |
|
---|
| 35 | struct buffer *exec_buf; /* Ptr to "Execution" buffer */
|
---|
| 36 | /* Only external ref is from e_buff.c */
|
---|
| 37 |
|
---|
| 38 | #define MSGLENGTH (scr_wid - 11) /* Max length of message */
|
---|
| 39 | int fresh_make = 1; /* Fresh Execution buffer contents */
|
---|
| 40 | chroff last_error_BOL; /* Dot for last-error's BOL */
|
---|
| 41 |
|
---|
| 42 | /* EFUN: "Execute Unix Command" */
|
---|
| 43 | f_xucmd()
|
---|
| 44 | {
|
---|
| 45 | make_or_unix_cmd(0);
|
---|
| 46 | }
|
---|
| 47 |
|
---|
| 48 | /* EFUN: "Execute Make" */
|
---|
| 49 | f_make()
|
---|
| 50 | {
|
---|
| 51 | make_or_unix_cmd(1);
|
---|
| 52 | }
|
---|
| 53 |
|
---|
| 54 | /* EFUN: "Find Next Error" */
|
---|
| 55 | f_nxterr()
|
---|
| 56 | {
|
---|
| 57 | register struct sbstr *sb;
|
---|
| 58 | register char *cp;
|
---|
| 59 | register int c;
|
---|
| 60 | char file[64], line[32];
|
---|
| 61 | #ifdef ONEWINDOW
|
---|
| 62 | char msg[512];
|
---|
| 63 | #endif
|
---|
| 64 | chroff linedot;
|
---|
| 65 | int lineno;
|
---|
| 66 | register int len;
|
---|
| 67 |
|
---|
| 68 | sel_execbuf();
|
---|
| 69 | if (! fresh_make)
|
---|
| 70 | { e_go(last_error_BOL);
|
---|
| 71 | e_gonl();
|
---|
| 72 | }
|
---|
| 73 | else
|
---|
| 74 | { fresh_make = 0;
|
---|
| 75 | e_gobob();
|
---|
| 76 | last_error_BOL = e_dot();
|
---|
| 77 | }
|
---|
| 78 |
|
---|
| 79 | /* Looking for `"file", line n: msg' */
|
---|
| 80 | if (! e_search("\", line ", 8, 0))
|
---|
| 81 | goto failed;
|
---|
| 82 | linedot = e_dot();
|
---|
| 83 | e_gobol(); /* Found something, get to BOL */
|
---|
| 84 | if (e_getc() != '"')
|
---|
| 85 | goto failed; /* Insist on beginning "file" */
|
---|
| 86 | cp = file; /* Pick up filename */
|
---|
| 87 | while ((c = e_getc()) != '"')
|
---|
| 88 | *cp++ = c;
|
---|
| 89 | *cp = 0;
|
---|
| 90 | e_go(linedot); /* Back to after "line " */
|
---|
| 91 | cp = line;
|
---|
| 92 | while ((c = e_getc()) >= '0' && c <= '9')
|
---|
| 93 | *cp++ = c;
|
---|
| 94 | *cp = 0;
|
---|
| 95 | lineno = atoi(line); /* Pick up line number */
|
---|
| 96 | #ifdef ONEWINDOW
|
---|
| 97 | cp = msg; /* Now get rest of line to msg */
|
---|
| 98 | len = 0; /* But keep length <= MSGLENGTH */
|
---|
| 99 | e_getc(); /* Go past purported space */
|
---|
| 100 | while ((c = e_getc()) != LF && c != EOF && len <= MSGLENGTH)
|
---|
| 101 | { if (c == '\t')
|
---|
| 102 | len = (len + 8) & ~07;
|
---|
| 103 | else if (c < ' ' || c > 0176)
|
---|
| 104 | len += 2;
|
---|
| 105 | else
|
---|
| 106 | ++len;
|
---|
| 107 | *cp++ = c;
|
---|
| 108 | }
|
---|
| 109 | *cp = 0;
|
---|
| 110 | if (len > MSGLENGTH)
|
---|
| 111 | strcat(msg, "...");
|
---|
| 112 | #ifdef DEBUG
|
---|
| 113 | say("file ");
|
---|
| 114 | saytoo(file);
|
---|
| 115 | saytoo(", line ");
|
---|
| 116 | saytoo(line);
|
---|
| 117 | saytoo(", msg: ");
|
---|
| 118 | sayntoo(msg);
|
---|
| 119 | #else
|
---|
| 120 | say(line);
|
---|
| 121 | saytoo(": ");
|
---|
| 122 | sayntoo(msg);
|
---|
| 123 | #endif /*DEBUG*/
|
---|
| 124 | #else /* -ONEWINDOW */
|
---|
| 125 | f_begline(); /* Get to start of line */
|
---|
| 126 | last_error_BOL = e_dot(); /* Remember this position */
|
---|
| 127 | exp_p = 1; /* Make this the new top line */
|
---|
| 128 | exp = 0;
|
---|
| 129 | f_newwin();
|
---|
| 130 | upd_wind(0);
|
---|
| 131 | #endif /*ONEWINDOW*/
|
---|
| 132 |
|
---|
| 133 | /* Now, visit the given file and line */
|
---|
| 134 | #ifdef ONEWINDOW
|
---|
| 135 | #else
|
---|
| 136 | f_othwind(); /* To other window */
|
---|
| 137 | #endif
|
---|
| 138 | find_file(file);
|
---|
| 139 | f_gobeg();
|
---|
| 140 | down_line(lineno - 1);
|
---|
| 141 | #ifdef READJUST /* NAW */
|
---|
| 142 | exp_p = 1;
|
---|
| 143 | exp = cur_win->w_ht / 4; /* Adjust how we look at "error" */
|
---|
| 144 | f_newwin();
|
---|
| 145 | #endif /*READJUST*/
|
---|
| 146 | return;
|
---|
| 147 |
|
---|
| 148 | failed: ding("No more errors!");
|
---|
| 149 | fresh_make = 1; /* Fake-out: pretend starting over */
|
---|
| 150 | return;
|
---|
| 151 | }
|
---|
| 152 | |
---|
| 153 |
|
---|
| 154 |
|
---|
| 155 | /* Do the "cmd" and put its output in the Execution buffer */
|
---|
| 156 | do_exec(cmd, nicely)
|
---|
| 157 | char *cmd;
|
---|
| 158 | int nicely;
|
---|
| 159 | {
|
---|
| 160 | register int n;
|
---|
| 161 | int status, res, pid, fd[2];
|
---|
| 162 | char nicecmd[256];
|
---|
| 163 | char pipebuff[512];
|
---|
| 164 | struct buffer *b;
|
---|
| 165 |
|
---|
| 166 | b = cur_buf;
|
---|
| 167 | sel_execbuf(); /* Get our execution buffer up */
|
---|
| 168 | ed_reset(); /* Clear it out */
|
---|
| 169 | fresh_make = 1;
|
---|
| 170 | upd_wind(0);
|
---|
| 171 | if (nicely)
|
---|
| 172 | sayntoo(" ...starting up...");
|
---|
| 173 | else
|
---|
| 174 | sayntoo(" ...starting up (nasty person)...");
|
---|
| 175 | pipe(fd);
|
---|
| 176 | switch (pid = fork())
|
---|
| 177 | {
|
---|
| 178 | case -1:
|
---|
| 179 | /* Fork failed, in parent */
|
---|
| 180 | ding("Cannot fork!?!");
|
---|
| 181 | break;
|
---|
| 182 |
|
---|
| 183 | case 0: /* In child */
|
---|
| 184 | for (n = 0; n < 20; ++n)
|
---|
| 185 | if (n != fd[0] && n != fd[1])
|
---|
| 186 | close(n);
|
---|
| 187 | open("/dev/null", 0); /* Give ourselves empty stdin */
|
---|
| 188 | dup(fd[1]);
|
---|
| 189 | dup(fd[1]); /* stdout, stderr out to pipe */
|
---|
| 190 | close(fd[1]); /* Close the pipe itself */
|
---|
| 191 | close(fd[0]);
|
---|
| 192 | if (nicely)
|
---|
| 193 | { strcpy(nicecmd, "nice -4 ");
|
---|
| 194 | strcat(nicecmd, cmd);
|
---|
| 195 | execl("/bin/sh", "sh", "-c", nicecmd, 0);
|
---|
| 196 | }
|
---|
| 197 | else
|
---|
| 198 | execl("/bin/sh", "sh", "-c", cmd, 0);
|
---|
| 199 | write(1, "Cannot execute!", 15);
|
---|
| 200 | _exit(-1);
|
---|
| 201 | break;
|
---|
| 202 |
|
---|
| 203 | default:
|
---|
| 204 | /* Parent */
|
---|
| 205 | close(fd[1]); /* Close the output direction */
|
---|
| 206 | while ((n = read(fd[0], pipebuff, sizeof(pipebuff))) > 0)
|
---|
| 207 | { ed_nsins(pipebuff, n);
|
---|
| 208 | upd_wind(0);
|
---|
| 209 | saynow("Chugging along...");
|
---|
| 210 | }
|
---|
| 211 | close(fd[0]);
|
---|
| 212 | while ((res = wait(&status)) != pid && res != -1)
|
---|
| 213 | ; /* Wait for this fork to die */
|
---|
| 214 | f_bufnotmod(); /* Buffer is fresh */
|
---|
| 215 | saynow("Done!");
|
---|
| 216 | break;
|
---|
| 217 | }
|
---|
| 218 | f_othwind(); /* Back to other window */
|
---|
| 219 | chg_buf(b); /* Back to original buffer */
|
---|
| 220 | }
|
---|
| 221 |
|
---|
| 222 | char last_make_cmd[256]; /* Last Unix/make command */
|
---|
| 223 | int have_last_make_cmd = 0;
|
---|
| 224 |
|
---|
| 225 | make_or_unix_cmd(domake)
|
---|
| 226 | int domake;
|
---|
| 227 | {
|
---|
| 228 | #if APOLLO
|
---|
| 229 | register int nicely = exp == 16; /* modification for apollo */
|
---|
| 230 | #else
|
---|
| 231 | register int nicely = exp != 16;
|
---|
| 232 | #endif /*-APOLLO*/
|
---|
| 233 | register char *reply, *cmd = 0;
|
---|
| 234 |
|
---|
| 235 | if (domake) /* If "make"-style, */
|
---|
| 236 | { int savp = exp_p;
|
---|
| 237 | exp_p = 1;
|
---|
| 238 | f_savefiles(); /* write modified files quietly */
|
---|
| 239 | exp_p = savp;
|
---|
| 240 | }
|
---|
| 241 | if (exp_p || ! domake)
|
---|
| 242 | { /* Arg given make, or Unix command */
|
---|
| 243 | reply = ask((! domake) ? "Unix command: " : "Command: ");
|
---|
| 244 | if (! reply)
|
---|
| 245 | return;
|
---|
| 246 | if (*reply == 0)
|
---|
| 247 | { if (have_last_make_cmd)
|
---|
| 248 | cmd = &last_make_cmd[0];
|
---|
| 249 | else
|
---|
| 250 | { chkfree(reply);
|
---|
| 251 | ding("No previous command!");
|
---|
| 252 | return;
|
---|
| 253 | }
|
---|
| 254 | }
|
---|
| 255 | else
|
---|
| 256 | cmd = reply;
|
---|
| 257 | if (cmd != &last_make_cmd[0]) /* Update last command */
|
---|
| 258 | strcpy(last_make_cmd, cmd);
|
---|
| 259 | have_last_make_cmd = 1;
|
---|
| 260 | say("Command: ");
|
---|
| 261 | sayntoo(cmd);
|
---|
| 262 | do_exec(cmd, nicely);
|
---|
| 263 | chkfree(reply);
|
---|
| 264 | }
|
---|
| 265 | else if (have_last_make_cmd)
|
---|
| 266 | { say("Command: ");
|
---|
| 267 | sayntoo(last_make_cmd);
|
---|
| 268 | do_exec(last_make_cmd, nicely);
|
---|
| 269 | }
|
---|
| 270 | else
|
---|
| 271 | { saynow("Command: make");
|
---|
| 272 | do_exec("make", nicely);
|
---|
| 273 | }
|
---|
| 274 | }
|
---|
| 275 | |
---|
| 276 |
|
---|
| 277 | sel_execbuf()
|
---|
| 278 | { if(!exec_buf)
|
---|
| 279 | { /* Make execution buffer; don't let anyone kill it */
|
---|
| 280 | exec_buf = make_buf("Execution");
|
---|
| 281 | exec_buf->b_flags |= B_PERMANENT;
|
---|
| 282 | }
|
---|
| 283 | popto_buf(exec_buf);
|
---|
| 284 | }
|
---|
| 285 |
|
---|
| 286 | /* Utility: pop the given buffer to a window, getting into 2-window mode */
|
---|
| 287 | popto_buf(b)
|
---|
| 288 | register struct buffer *b;
|
---|
| 289 | {
|
---|
| 290 | /* See if we already have this buffer in a visible window */
|
---|
| 291 | if (b == cur_win->w_buf)
|
---|
| 292 | { if (oth_win == 0)
|
---|
| 293 | { f_2winds();
|
---|
| 294 | f_othwind(); /* Get back to our window */
|
---|
| 295 | }
|
---|
| 296 | }
|
---|
| 297 | else if (oth_win != 0 && b == oth_win->w_buf)
|
---|
| 298 | f_othwind();
|
---|
| 299 | else if (oth_win == 0)
|
---|
| 300 | { /* One window mode */
|
---|
| 301 | f_2winds(); /* Get two, get into second */
|
---|
| 302 | sel_buf(b); /* Select our new buffer */
|
---|
| 303 | }
|
---|
| 304 | else
|
---|
| 305 | { f_othwind(); /* Get to other window */
|
---|
| 306 | sel_buf(b); /* and select our buffer */
|
---|
| 307 | }
|
---|
| 308 | }
|
---|
| 309 |
|
---|
| 310 | #endif /*IMAGEN*/
|
---|