home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / editor / j414src.arc / PROC.C < prev    next >
C/C++ Source or Header  |  1989-10-10  |  20KB  |  892 lines

  1. /***************************************************************************
  2.  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  3.  * is provided to you without charge, and with no warranty.  You may give  *
  4.  * away copies of JOVE, including sources, provided that this notice is    *
  5.  * included in all the files.                                              *
  6.  ***************************************************************************/
  7.  
  8. #include "jove.h"
  9. #include "ctype.h"
  10. #include "fp.h"
  11. #include "re.h"
  12. #include "termcap.h"
  13. #include "disp.h"
  14.  
  15. #include <signal.h>
  16. #ifdef    STDARGS
  17. # include <stdarg.h>
  18. #else
  19. # include <varargs.h>
  20. #endif
  21.  
  22. #ifdef MSDOS
  23. # include <io.h>
  24. # include <process.h>
  25. #endif
  26.  
  27. private void
  28.     DoShell proto((char *, char *)),
  29.     com_finish proto((int, char *)),
  30.     toerror proto((int, int));
  31.  
  32. #ifdef    MSDOS
  33. private void
  34.     closepipe proto((void));
  35. #endif
  36.  
  37. private int
  38.     okay_error proto((void));
  39.  
  40. #if defined(MSDOS)
  41. private int
  42.     openforpipe proto((void)),
  43.     reopenforpipe proto((void));
  44. #endif
  45.  
  46. private struct error
  47.     *AddError proto((struct error *, Line *, Buffer *, Line *, int));
  48.  
  49. long    SigMask = 0;
  50.  
  51. /* This disgusting RE search string parses output from the GREP
  52.    family, from the pdp11 compiler, pcc, and lint.  Jay (HACK)
  53.    Fenlasen changed this to work for the lint errors. */
  54. char    ErrFmtStr[256] = "^\\{\",\\}\\([^:\"( \t]*\\)\\{\"\\, line ,:,(\\} *\\([0-9][0-9]*\\)[:)]\
  55. \\|::  *\\([^(]*\\)(\\([0-9]*\\))$\
  56. \\|( \\([^(]*\\)(\\([0-9]*\\)) ),";
  57.  
  58. struct error {
  59.     Buffer        *er_buf;    /* Buffer error is in */
  60.     Line        *er_mess,    /* Actual error message */
  61.             *er_text;    /* Actual error */
  62.     int        er_char;    /* char pos of error */
  63.     struct error    *er_prev,    /* List of errors */
  64.             *er_next;
  65. };
  66.  
  67. private struct error    *cur_error = NULL,
  68.         *errorlist = NULL;
  69. Buffer        *perr_buf = NULL;    /* Buffer with error messages */
  70.  
  71. int    WtOnMk = 1;        /* Write the modified files when we make */
  72.  
  73. /* Add an error to the end of the list of errors.  This is used for
  74.    parse-{C,LINT}-errors and for the spell-buffer command */
  75.  
  76. private struct error *
  77. AddError(laste, errline, buf, line, charpos)
  78. struct error    *laste;
  79. Line    *errline,
  80.     *line;
  81. Buffer    *buf;
  82. int    charpos;
  83. {
  84.     struct error    *new = (struct error *) emalloc(sizeof *new);
  85.  
  86.     new->er_prev = laste;
  87.     if (laste)
  88.         laste->er_next = new;
  89.     else {
  90.         if (errorlist)        /* Free up old errors */
  91.             ErrFree();
  92.         cur_error = errorlist = new;
  93.     }
  94.     laste = new;
  95.     new->er_next = 0;
  96.     new->er_buf = buf;
  97.     new->er_text = line;
  98.     new->er_char = charpos;
  99.     new->er_mess = errline;
  100.  
  101.     return new;
  102. }
  103.  
  104. void
  105. get_FL_info(fname, lineno)
  106. char    *fname,
  107.     *lineno;
  108. {
  109.     putmatch(1, fname, (size_t)FILESIZE);
  110.     putmatch(2, lineno, (size_t)FILESIZE);
  111.  
  112.     /* error had lineno followed fname, so switch the two */
  113.     if (!isdigit(lineno[0])) {
  114.         char    tmp[FILESIZE];
  115.  
  116.         strcpy(tmp, lineno);
  117.         strcpy(lineno, fname);
  118.         strcpy(fname, tmp);
  119.     }
  120. }
  121.  
  122. /* Free up all the errors */
  123.  
  124. void
  125. ErrFree()
  126. {
  127.     register struct error    *ep;
  128.  
  129.     for (ep = errorlist; ep != 0; ep = ep->er_next)
  130.         free((char *) ep);
  131.     errorlist = cur_error = 0;
  132. }
  133.  
  134. /* Parse errors of the form specified in ErrFmtStr in the current
  135.    buffer.  Do a show error of the first error.  This is neat because this
  136.    will work for any kind of output that prints a file name and a line
  137.    number on the same line. */
  138.  
  139. void
  140. ErrParse()
  141. {
  142.     struct RE_block    re_blk;
  143.     Bufpos    *bp;
  144.     char    fname[FILESIZE],
  145.         lineno[FILESIZE];
  146.     int    lnum,
  147.         last_lnum = -1;
  148.     struct error    *ep = 0;
  149.     Buffer    *buf,
  150.         *lastb = 0;
  151.     Line    *err_line;
  152.  
  153.     ErrFree();        /* This is important! */
  154.     ToFirst();
  155.     perr_buf = curbuf;
  156.     REcompile(ErrFmtStr, YES, &re_blk);
  157.     /* Find a line with a number on it. */
  158.     while ((bp = docompiled(FORWARD, &re_blk)) != NULL) {
  159.         SetDot(bp);
  160.         get_FL_info(fname, lineno);
  161.         buf = do_find((Window *) 0, fname, YES);
  162.         if (buf != lastb) {
  163.             lastb = buf;
  164.             last_lnum = -1;        /* signals new file */
  165.             err_line = buf->b_first;
  166.         }
  167.         (void) chr_to_int(lineno, 10, NO, &lnum);
  168.         if (lnum == last_lnum)    /* one error per line is nicer */
  169.             continue;
  170.         if (last_lnum == -1)
  171.             last_lnum = 1;    /* that's where we really are */
  172.         err_line = next_line(err_line, lnum - last_lnum);
  173.         ep = AddError(ep, curline, buf, err_line, 0);
  174.         last_lnum = lnum;
  175.     }
  176.     if (cur_error != 0)
  177.         ShowErr();
  178. }
  179.  
  180. /* Internal next error sets cur_error to the next error, taking the
  181.    argument count, supplied by the user, into consideration. */
  182.  
  183. private char    errbounds[] = "You're at the %s error.",
  184.         noerrs[] = "No errors!";
  185.  
  186. private void
  187. toerror(forward, num)
  188. int    forward,
  189.     num;
  190. {
  191.     register struct error    *e = cur_error;
  192.  
  193.     if (e == 0)
  194.         complain(noerrs);
  195.     if ((forward && (e->er_next == 0)) ||
  196.         (!forward && (e->er_prev == 0)))
  197.         complain(errbounds, forward ? "last" : "first");
  198.  
  199.     while (--num >= 0) {
  200.         if ((e = forward ? e->er_next : e->er_prev) == 0)
  201.             break;
  202.         cur_error = e;
  203.     }
  204. }
  205.  
  206. void
  207. NextError()
  208. {
  209.     ToError(1);
  210. }
  211.  
  212. void
  213. PrevError()
  214. {
  215.     ToError(0);
  216. }
  217.  
  218. private int
  219. okay_error()
  220. {
  221.     return ((inlist(perr_buf->b_first, cur_error->er_mess)) &&
  222.         (inlist(cur_error->er_buf->b_first, cur_error->er_text)));
  223. }
  224.  
  225. /* Go the the next error, if there is one.  Put the error buffer in
  226.    one window and the buffer with the error in another window.
  227.    It checks to make sure that the error actually exists. */
  228.  
  229. void
  230. ToError(forward)
  231. int    forward;
  232. {
  233.     do {
  234.         toerror(forward, arg_value());
  235.     } while (!okay_error());
  236.     ShowErr();
  237. }
  238.  
  239. int    EWSize = 20;    /* percentage of screen the error window
  240.                should be */
  241.  
  242. private void
  243. set_wsize(wsize)
  244. int    wsize;
  245. {
  246.     wsize = (LI * wsize) / 100;
  247.     if (wsize >= 1 && !one_windp())
  248.         WindSize(curwind, wsize - (curwind->w_height - 1));
  249. }
  250.  
  251. /* Show the current error, i.e. put the line containing the error message
  252.    in one window, and the buffer containing the actual error in another
  253.    window. */
  254.  
  255. void
  256. ShowErr()
  257. {
  258.     Window    *err_wind,
  259.         *buf_wind;
  260.  
  261.     if (cur_error == 0)
  262.         complain(noerrs);
  263.     if (!okay_error()) {
  264.         rbell();
  265.         return;
  266.     }
  267.     err_wind = windbp(perr_buf);
  268.     buf_wind = windbp(cur_error->er_buf);
  269.  
  270.     if (err_wind && !buf_wind) {
  271.         SetWind(err_wind);
  272.         pop_wind(cur_error->er_buf->b_name, NO, -1);
  273.         buf_wind = curwind;
  274.     } else if (!err_wind && buf_wind) {
  275.         SetWind(buf_wind);
  276.         pop_wind(perr_buf->b_name, NO, -1);
  277.         err_wind = curwind;
  278.     } else if (!err_wind && !buf_wind) {
  279.         pop_wind(perr_buf->b_name, NO, -1);
  280.         err_wind = curwind;
  281.         pop_wind(cur_error->er_buf->b_name, NO, -1);
  282.         buf_wind = curwind;
  283.     }
  284.  
  285.     /* Put the current error message at the top of its Window */
  286.     SetWind(err_wind);
  287.     SetLine(cur_error->er_mess);
  288.     SetTop(curwind, (curwind->w_line = cur_error->er_mess));
  289.     set_wsize(EWSize);
  290.  
  291.     /* now go to the the line with the error in the other window */
  292.     SetWind(buf_wind);
  293.     DotTo(cur_error->er_text, cur_error->er_char);
  294. }
  295.  
  296. char    ShcomBuf[LBSIZE];
  297.  
  298. /* Make a buffer name given the command `command', i.e. "fgrep -n foo *.c"
  299.    will return the buffer name "fgrep".  */
  300.  
  301. char *
  302. MakeName(command)
  303. char    *command;
  304. {
  305.     static char    bnm[50];
  306.     register char    *cp = bnm,
  307.             c;
  308.  
  309.     while ((c = *command++) != '\0' && (c == ' ' || c == '\t'))
  310.         ;
  311.     do
  312.         *cp++ = c;
  313.     while ((c = *command++) != '\0' && (c != ' ' && c != '\t'));
  314.     *cp = 0;
  315.     strcpy(bnm, basename(bnm));
  316.  
  317.     return bnm;
  318. }
  319.  
  320. /* Run make, first writing all the modified buffers (if the WtOnMk flag is
  321.    non-zero), parse the errors, and go the first error. */
  322.  
  323. private char    make_cmd[LBSIZE] = "make";
  324.  
  325. void
  326. MakeErrors()
  327. {
  328.     Window    *old = curwind;
  329.     int    status,
  330.         compilation;
  331.  
  332.     if (WtOnMk)
  333.         put_bufs(0);
  334.     /* When we're not doing make or cc (i.e., the last command
  335.        was probably a grep or something) and the user just types
  336.        C-X C-E, he probably (possibly, hopefully, usually (in my
  337.        case)) doesn't want to do the grep again but rather wants
  338.        to do a make again; so we ring the bell and insert the
  339.        default command and let the person decide. */
  340.  
  341.     compilation = (sindex("make", make_cmd) || sindex("cc", make_cmd));
  342.     if (is_an_arg() || !compilation) {
  343.         if (!compilation) {
  344.             rbell();
  345.             Inputp = make_cmd;    /* insert the default for the user */
  346.         }
  347.         null_ncpy(make_cmd, ask(make_cmd, "Compilation command: "),
  348.                 sizeof (make_cmd) - 1);
  349.     }
  350.     status = UnixToBuf(MakeName(make_cmd), YES, EWSize, YES, Shell, ShFlags, make_cmd, (char *) 0);
  351.     com_finish(status, make_cmd);
  352.  
  353.     ErrParse();
  354.  
  355.     if (!cur_error)
  356.         SetWind(old);
  357. }
  358.  
  359. #ifdef SPELL
  360.  
  361. private void
  362. SpelParse(bname)
  363. char    *bname;
  364. {
  365.     Buffer    *buftospel,
  366.         *wordsb;
  367.     char    wordspel[100];
  368.     Bufpos    *bp;
  369.     struct error    *ep = 0;
  370.  
  371.     ErrFree();        /* This is important! */
  372.  
  373.     buftospel = curbuf;
  374.     wordsb = buf_exists(bname);
  375.     perr_buf = wordsb;    /* This is important (buffer containing
  376.                    error messages) */
  377.     SetBuf(wordsb);
  378.     ToFirst();
  379.     f_mess("Finding misspelled words ... ");
  380.     while (!lastp(curline)) {
  381.         swritef(wordspel, "\\<%s\\>", linebuf);
  382.         SetBuf(buftospel);
  383.         ToFirst();
  384.         while ((bp = dosearch(wordspel, 1, 1)) != NULL) {
  385.             SetDot(bp);
  386.             ep = AddError(ep, wordsb->b_dot, buftospel,
  387.                       curline, curchar);
  388.         }
  389.         SetBuf(wordsb);
  390.         line_move(FORWARD, 1, NO);
  391.     }
  392.     add_mess("Done.");
  393.     SetBuf(buftospel);
  394.     ShowErr();
  395. }
  396.  
  397. void
  398. SpelBuffer()
  399. {
  400.     char    *Spell = "Spell",
  401.         com[100];
  402.     Window    *savewp = curwind;
  403.  
  404.     put_bufs(0);
  405.     swritef(com, "spell %s", curbuf->b_fname);
  406.     (void) UnixToBuf(Spell, YES, EWSize, YES, Shell, ShFlags, com, (char *) 0);
  407.     message("[Delete the irrelevant words and then type C-X C-C]");
  408.     ToFirst();
  409.     Recur();
  410.     SetWind(savewp);
  411.     SpelParse(Spell);
  412. }
  413.  
  414. void
  415. SpelWords()
  416. {
  417.     char    *buftospel;
  418.     Buffer    *wordsb = curbuf;
  419.  
  420.     if ((buftospel = ask_buf((Buffer *) 0)) == 0)
  421.         return;
  422.     SetBuf(do_select(curwind, buftospel));
  423.     SpelParse(wordsb->b_name);
  424. }
  425.  
  426. #endif /* SPELL */
  427.  
  428. void
  429. ShToBuf()
  430. {
  431.     char    bnm[128],
  432.         cmd[128];
  433.  
  434.     strcpy(bnm, ask((char *) 0, "Buffer: "));
  435.     strcpy(cmd, ask(ShcomBuf, "Command: "));
  436.     DoShell(bnm, cmd);
  437. }
  438.  
  439. void
  440. ShellCom()
  441. {
  442.     null_ncpy(ShcomBuf, ask(ShcomBuf, ProcFmt), (sizeof ShcomBuf) - 1);
  443.     DoShell(MakeName(ShcomBuf), ShcomBuf);
  444. }
  445.  
  446. void
  447. ShNoBuf()
  448. {
  449.     int    status;
  450.  
  451.     null_ncpy(ShcomBuf, ask(ShcomBuf, ProcFmt), (sizeof ShcomBuf) - 1);
  452.     status = UnixToBuf((char *) 0, NO, 0, NO, Shell, ShFlags, ShcomBuf,
  453.         curbuf->b_fname, curbuf->b_fname, (char *) 0);
  454.     com_finish(status, ShcomBuf);
  455. }
  456.  
  457. void
  458. Shtypeout()
  459. {
  460.     int    status;
  461.  
  462.     null_ncpy(ShcomBuf, ask(ShcomBuf, ProcFmt), (sizeof ShcomBuf) - 1);
  463.     status = UnixToBuf((char *) 0, YES, 0, NO, Shell, ShFlags, ShcomBuf,
  464.         curbuf->b_fname, curbuf->b_fname, (char *) 0);
  465.     if (status == 0)
  466.         Typeout("[%s: completed successfully]", ShcomBuf);
  467.     else
  468.         Typeout("[%s: exited (%d)]", ShcomBuf, status);
  469.     TOstop();
  470. }
  471.  
  472. /* Run the shell command into `bnm'.  Empty the buffer except when we
  473.    give a numeric argument, in which case it inserts the output at the
  474.    current position in the buffer.  */
  475.  
  476. private void
  477. DoShell(bnm, command)
  478. char    *bnm,
  479.     *command;
  480. {
  481.     Window    *savewp = curwind;
  482.     int    status;
  483.  
  484.     status = UnixToBuf(bnm, YES, 0, !is_an_arg(), Shell, ShFlags,
  485.         command, curbuf->b_fname, curbuf->b_fname, (char *) 0);
  486.     com_finish(status, command);
  487.     SetWind(savewp);
  488. }
  489.  
  490. private void
  491. com_finish(status, cmd)
  492. int    status;
  493. char    *cmd;
  494. {
  495.     s_mess("[%s: ", cmd);
  496.     if (status == 0)
  497.         add_mess("completed successfully");
  498.     else
  499.         add_mess("exited (%d)", status);
  500.     add_mess("]");
  501. }
  502.  
  503. #ifndef MSDOS
  504. void
  505. dowait(pid, status)
  506. int    pid,
  507.     *status;
  508. {
  509. # ifndef IPROCS
  510.  
  511.     int    rpid;
  512.  
  513.     while ((rpid = wait(status)) != pid)
  514.         ;
  515. # else
  516.  
  517. # include "wait.h"
  518.  
  519.     union wait    w;
  520.     int    rpid;
  521.  
  522.     for (;;) {
  523. #  ifndef WAIT3
  524.         rpid = wait2(&w.w_status, 0);
  525. #  else
  526.         rpid = wait3(&w, 0, (struct rusage *) 0);
  527. #  endif
  528.         if (rpid == -1)
  529.             break;
  530.         else if (rpid == pid) {
  531.             if (status)
  532.                 *status = w.w_status;
  533.             break;
  534.         } else
  535.             kill_off(rpid, w);
  536.     }
  537. # endif /* IPROCS */
  538. }
  539. #endif /* MSDOS */
  540.  
  541. /* Run the command to bnm, erase the buffer if clobber is non-zero,
  542.    and redisplay if disp is non-zero.  Leaves current buffer in `bnm'
  543.    and leaves any windows it creates lying around.  It's up to the caller
  544.    to fix everything up after we're done.  (Usually there's nothing to
  545.    fix up.) */
  546.  
  547. #ifdef    STDARGS
  548.     int
  549. UnixToBuf(char *bnm, int disp, int wsize, int clobber, ...)
  550. #else
  551.     /*VARARGS4*/ int
  552. UnixToBuf(bnm, disp, wsize, clobber, va_alist)
  553.     char    *bnm;
  554.     int    disp;
  555.     int    wsize;
  556.     int    clobber;
  557.     va_dcl
  558. #endif
  559. {
  560. #ifndef MSDOS
  561.     int    p[2],
  562.         pid,
  563.         status,
  564. #else /* MSDOS */
  565.     int    p0,
  566.         oldo,
  567.         olde,
  568.         retcode,
  569. #endif /* MSDOS */
  570.         eof;
  571.     va_list    ap;
  572.     char    *argv[32],
  573.         *mess;
  574.     File    *fp;
  575.     SIGRESULT    (*old_int) proto((int));
  576.  
  577.     va_init(ap, clobber);
  578.     make_argv(argv, ap);
  579.     va_end(ap);
  580.     if (bnm != 0 && clobber == YES)
  581.         isprocbuf(bnm);
  582.     if (disp) {
  583.         if (bnm != 0)
  584.             message("Starting up...");
  585.         else {
  586.             TOstart(argv[0], TRUE);
  587.             Typeout("Starting up...");
  588.         }
  589.         if (bnm != 0) {
  590.             pop_wind(bnm, clobber, clobber ? B_PROCESS : B_FILE);
  591.             set_wsize(wsize);
  592.             redisplay();
  593.         }
  594.     }
  595.     /* Now I will attempt to describe how I deal with signals during
  596.        the execution of the shell command.  My desire was to be able
  597.        to interrupt the shell command AS SOON AS the window pops up.
  598.        So, if we have JOB_CONTROL (i.e., the new signal mechanism) I
  599.        hold SIGINT, meaning if we interrupt now, we will eventually
  600.        see the interrupt, but not before we are ready for it.  We
  601.        fork, the child releases the interrupt, it then sees the
  602.        interrupt, and so exits.  Meanwhile the parent ignores the
  603.        signal, so if there was a pending one, it's now lost.
  604.  
  605.        With no JOB_CONTROL, the best behavior you can expect is, when
  606.        you type ^] too very quickly after the window pops up, it may
  607.        be ignored.  The behavior BEFORE was that it would interrupt
  608.        JOVE and then you would have to continue JOVE and wait a
  609.        little while longer before trying again.  Now that is fixed,
  610.        in that you just have to type it twice. */
  611.  
  612. #ifndef MSDOS
  613. # ifdef IPROCS
  614.     SigHold(SIGCHLD);
  615. # endif
  616. # ifdef JOB_CONTROL
  617.     SigHold(SIGINT);
  618. # else
  619.     old_int = signal(SIGINT, SIG_IGN),
  620. # endif
  621.     dopipe(p);
  622.     pid = vfork();
  623.     if (pid == -1) {
  624.         pclose(p);
  625.         complain("[Fork failed]");
  626.     }
  627.     if (pid == 0) {
  628. # ifdef BSD_SIGS
  629.         /*
  630.          * We want to release SIGCHLD and SIGINT in the child, but
  631.          * we can't use SigRelse because that would change Jove's
  632.          * copy of the SigMask variable (because we're in a
  633.          * vfork).  So we simply set set the mask directly.  There
  634.          * are several other forks in Jove, but this is the only
  635.          * one we execute often enough to make it worth using a
  636.          * vfork.
  637.          */
  638.         (void) signal(SIGINT, SIG_DFL);
  639.         (void) sigsetmask(SigMask & ~(sigmask(SIGCHLD)|sigmask(SIGINT)));
  640. # else /* BSD_SIGS */
  641. # ifdef IPROCS
  642.         SigRelse(SIGCHLD);   /* don't know if this matters */
  643. # endif /* IPROCS */
  644.         (void) signal(SIGINT, SIG_DFL);
  645. # ifdef JOB_CONTROL
  646.         SigRelse(SIGINT);
  647. # endif
  648. # endif /* BSD_SIGS */
  649.         (void) close(0);
  650.         (void) open("/dev/null", 0);
  651.         (void) close(1);
  652.         (void) close(2);
  653.         (void) dup(p[1]);
  654.         (void) dup(p[1]);
  655.         pclose(p);
  656.         execv(argv[0], (const char **) &argv[1]);
  657.         (void) write(1, "Execl failed.\n", (size_t) 14);
  658.         _exit(1);
  659.     }
  660. # ifdef JOB_CONTROL
  661.     old_int = signal(SIGINT, SIG_IGN);
  662. # endif
  663.     (void) close(p[1]);
  664.     fp = fd_open(argv[1], F_READ, p[0], iobuff, LBSIZE);
  665. #else /* MSDOS */
  666.     if ((p0 = openforpipe()) < 0)
  667.        complain("cannot make pipe for filter");
  668.  
  669.     oldo = dup(1);
  670.     olde = dup(2);
  671.     close(1);
  672.     close(2);
  673.     dup(p0);
  674.     dup(1);
  675.     close(p0);
  676.     retcode = spawnv(0, argv[0], &argv[1]);
  677.     p0 = reopenforpipe();
  678.     close(1);
  679.     close(2);
  680.     dup(oldo);
  681.     dup(olde);
  682.     close(oldo);
  683.     close(olde);
  684.  
  685.     if (retcode < 0)
  686.         complain("[Spawn failed]");
  687.  
  688.     fp = fd_open(argv[1], F_READ, p0, iobuff, LBSIZE);
  689. #endif /* MSDOS */
  690.     do {
  691. #ifndef MSDOS
  692.         inIOread = 1;
  693. #endif
  694.         eof = f_gets(fp, genbuf, (size_t)LBSIZE);
  695. #ifndef MSDOS
  696.         inIOread = 0;
  697. #endif
  698.         if (bnm != 0) {
  699.             ins_str(genbuf, YES);
  700.             if (!eof)
  701.                 LineInsert(1);
  702.         } else if (disp == YES)
  703.             Typeout("%s", genbuf);
  704.         if (bnm != 0 && disp != 0 && fp->f_cnt <= 0) {
  705. #ifdef LOAD_AV
  706.             {
  707.             double    theavg;
  708.  
  709.             get_la(&theavg);
  710.             if (theavg < 2.0)
  711.                 mess = "Screaming along...";
  712.             else if (theavg < 5.0)
  713.                 mess = "Chugging along...";
  714.             else
  715.                 mess = "Crawling along...";
  716.             }
  717. #else
  718.             mess = "Chugging along...";
  719. #endif /* LOAD_AV */
  720.             if (bnm != 0) {
  721.                 message(mess);
  722.                 redisplay();
  723.             }
  724.         }
  725.     } while (!eof);
  726.     if (disp)
  727.         DrawMesg(NO);
  728.     close_file(fp);
  729. #ifndef MSDOS
  730.     dowait(pid, &status);
  731. # ifdef JOB_CONTROL
  732.     (void) SigRelse(SIGINT);
  733. # endif
  734. #else /* MSDOS */
  735.     closepipe();
  736. #endif /* MSDOS */
  737.     (void) signal(SIGINT, old_int);
  738. #ifndef MSDOS
  739. # ifdef IPROCS
  740.     SigRelse(SIGCHLD);
  741. # endif
  742.     return status;
  743. #else /* MSDOS */
  744.     getCWD();
  745.     return retcode;
  746. #endif /* MSDOS */
  747. }
  748.  
  749. /* Send the current region to CMD and insert the output from the
  750.    command into OUT_BUF. */
  751.  
  752. void
  753. RegToUnix(outbuf, cmd)
  754. Buffer    *outbuf;
  755. char    *cmd;
  756. {
  757.     Mark    *m = CurMark();
  758. #ifndef MSDOS
  759.     static char     tnambuf[20];
  760.     char    *tname,
  761.         combuf[128];
  762. #endif /* MSDOS */
  763.     Window    *save_wind = curwind;
  764.     int    status,
  765.         err = NO;
  766. #ifdef MSDOS
  767.     int p0, oldi;
  768. #endif /* MSDOS */
  769.     File    *fp;
  770.  
  771. #ifndef MSDOS
  772.     strcpy (tnambuf, "/tmp/jfilterXXXXXX");
  773.     tname = mktemp(tnambuf);
  774.     fp = open_file(tname, iobuff, F_WRITE, YES, YES);
  775. #else /* MSDOS */
  776.     p0 = openforpipe();
  777. #endif /* MSDOS */
  778.     CATCH
  779. #ifdef MSDOS
  780.     fp = fd_open(cmd, F_WRITE, p0, iobuff, LBSIZE);
  781. #endif /* MSDOS */
  782.     putreg(fp, m->m_line, m->m_char, curline, curchar, YES);
  783.     DelReg();
  784. #ifndef MSDOS
  785.     swritef(combuf, "%s < %s", cmd, tname);
  786. #else /* MSDOS */
  787.     f_close(fp);
  788.     p0 = reopenforpipe();
  789.     oldi = dup(0);
  790.     close(0);
  791.     dup(p0);
  792.     close(p0);
  793. #endif /* MSDOS */
  794.     status = UnixToBuf(outbuf->b_name, NO, 0, outbuf->b_type == B_SCRATCH,
  795. #ifndef MSDOS
  796.                Shell, ShFlags, combuf, (char *) 0
  797. #else /* MSDOS */
  798.                Shell, ShFlags, cmd, (char *) 0
  799. #endif /* MSDOS */
  800.                );
  801.     ONERROR
  802.     err = YES;
  803.     ENDCATCH
  804. #ifndef MSDOS
  805.     f_close(fp);
  806.     (void) unlink(tname);
  807. #else /* MSDOS */
  808.     close(0);
  809.     open("con", 0);    /* dup(oldi);    */
  810.     close(oldi);
  811.     closepipe();
  812. #endif /* MSDOS */
  813.     SetWind(save_wind);
  814.     if (err == NO)
  815. #ifndef MSDOS
  816.         com_finish(status, combuf);
  817. #else
  818.         com_finish(status, cmd);
  819. #endif
  820. }
  821.  
  822. void
  823. FilterRegion()
  824. {
  825.     static char    FltComBuf[LBSIZE];
  826.  
  827.     null_ncpy(FltComBuf, ask(FltComBuf, ": %f (through command) "),
  828.         (sizeof FltComBuf) - 1);
  829.     RegToUnix(curbuf, FltComBuf);
  830. }
  831.  
  832. void
  833. isprocbuf(bnm)
  834. char    *bnm;
  835. {
  836.     Buffer    *bp;
  837.  
  838.     if ((bp = buf_exists(bnm)) != 0 && bp->b_type != B_PROCESS)
  839.         confirm("Over-write buffer %s?", bnm);
  840. }
  841.  
  842. #ifdef MSDOS
  843. /*    msdos specific hacks to allow for pipes */
  844.  
  845. #include <dos.h>
  846. #include <fcntl.h>
  847. #include <sys/stat.h>
  848.  
  849. static char pipeiname[64];
  850. static char pipeoname[64];
  851. static int  pipehandle;
  852.  
  853. private int
  854. openforpipe()
  855. {
  856.    swritef(pipeiname, "%s/%s", TmpFilePath, "Jove-I");
  857.    swritef(pipeoname, "%s/%s", TmpFilePath, "Jove-O");
  858.  
  859.    return(pipehandle = creat(pipeoname, S_IWRITE|S_IREAD));
  860. }
  861.  
  862. private int
  863. reopenforpipe()
  864. {
  865.    close(pipehandle);
  866.    unlink(pipeiname);
  867.    rename(pipeoname, pipeiname);
  868.    if ((pipehandle = open(pipeiname, 0)) >= 0)
  869.       return(pipehandle);
  870.    closepipe();
  871.    return(-1);
  872. }
  873.  
  874. private void
  875. closepipe()
  876. {
  877.    unlink(pipeoname);
  878.    unlink(pipeiname);
  879. }
  880.  
  881. char
  882. switchar()
  883. {
  884.   union REGS regs;
  885.  
  886.   regs.h.ah = 0x37;
  887.   regs.h.al = 0;
  888.   intdos(®s, ®s);
  889.   return(regs.h.dl);
  890. }
  891. #endif /* MSDOS */
  892.