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

Defined functions

AddError defined in line 78; used 4 times
DoShell defined in line 454; used 4 times
ErrFree defined in line 155; used 6 times
ErrParse defined in line 110; used 4 times
FilterRegion defined in line 725; used 4 times
MakeErrors defined in line 307; used 4 times
MakeName defined in line 283; used 6 times
NextError defined in line 189; used 4 times
PrevError defined in line 195; used 4 times
RegToUnix defined in line 736; used 3 times
ShNoBuf defined in line 428; used 2 times
ShToBuf defined in line 410; used 4 times
ShellCom defined in line 421; used 4 times
ShowErr defined in line 237; used 7 times
Shtypeout defined in line 437; used 2 times
SpelBuffer defined in line 343; used 2 times
SpelParse defined in line 372; used 2 times
SpelWords defined in line 360; used 2 times
ToError defined in line 212; used 4 times
UnixToBuf defined in line 529; used 9 times
closepipe defined in line 847; used 5 times
com_finish defined in line 468; used 7 times
dowait defined in line 482; used 3 times
okay_error defined in line 201; used 4 times
openforpipe defined in line 826; used 4 times
reopenforpipe defined in line 835; used 4 times
set_wsize defined in line 224; used 4 times
switchar defined in line 854; used 3 times
toerror defined in line 171; used 3 times

Defined variables

EWSize defined in line 221; used 7 times
ErrFmtStr defined in line 56; used 3 times
ShcomBuf defined in line 278; used 17 times
SigMask defined in line 51; used 3 times
WtOnMk defined in line 73; used 3 times
cur_error defined in line 69; used 17 times
errbounds defined in line 168; used 1 times
make_cmd defined in line 305; used 9 times
perr_buf defined in line 71; used 6 times
pipehandle defined in line 822; used 4 times
pipeiname defined in line 820; used 5 times
pipeoname defined in line 821; used 4 times
private defined in line 847; never used

Defined struct's

error defined in line 60; used 23 times
Last modified: 1988-08-11
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5673
Valid CSS Valid XHTML 1.0 Strict