Annotation of 43BSD/contrib/jove/proc.c, revision 1.1.1.1

1.1       root        1: /*************************************************************************
                      2:  * This program is copyright (C) 1985, 1986 by Jonathan Payne.  It is    *
                      3:  * provided to you without charge for use only on a licensed Unix        *
                      4:  * system.  You may copy JOVE provided that this notice is included with *
                      5:  * the copy.  You may not sell copies of this program or versions        *
                      6:  * modified for use on microcomputer systems, unless the copies are      *
                      7:  * included with a Unix system distribution and the source is provided.  *
                      8:  *************************************************************************/
                      9: 
                     10: #include "jove.h"
                     11: #include "io.h"
                     12: #include "termcap.h"
                     13: 
                     14: #include <signal.h>
                     15: 
                     16: private char
                     17:        *errfmt = "^\\{\",\\}\\([^:\"( \t]*\\)\\{\"\\, line ,:,(\\} *\\([0-9][0-9]*\\)[:)]";
                     18: 
                     19: struct error {
                     20:        Buffer          *er_buf;        /* Buffer error is in */
                     21:        Line            *er_mess,       /* Actual error message */
                     22:                        *er_text;       /* Actual error */
                     23:        int             er_char;        /* char pos of error */
                     24:        struct error    *er_prev,       /* List of errors */
                     25:                        *er_next;
                     26: };
                     27: 
                     28: struct error   *cur_error = 0,
                     29:                *errorlist = 0;
                     30: Buffer         *perr_buf = 0;  /* Buffer with error messages */
                     31: 
                     32: int    WtOnMk = 1;             /* Write the modified files when we make */
                     33: 
                     34: /* Add an error to the end of the list of errors.  This is used for
                     35:    parse-{C,LINT}-errors and for the spell-buffer command */
                     36: 
                     37: private struct error *
                     38: AddError(laste, errline, buf, line, charpos)
                     39: struct error   *laste;
                     40: Line   *errline,
                     41:        *line;
                     42: Buffer *buf;
                     43: {
                     44:        struct error    *new = (struct error *) emalloc(sizeof *new);
                     45: 
                     46:        new->er_prev = laste;
                     47:        if (laste)
                     48:                laste->er_next = new;
                     49:        else {
                     50:                if (errorlist)          /* Free up old errors */
                     51:                        ErrFree();
                     52:                cur_error = errorlist = new;
                     53:        }
                     54:        laste = new;
                     55:        new->er_next = 0;
                     56:        new->er_buf = buf;
                     57:        new->er_text = line;
                     58:        new->er_char = charpos;
                     59:        new->er_mess = errline;
                     60: 
                     61:        return new;
                     62: }
                     63: 
                     64: ParseAll()
                     65: {
                     66:        ErrParse(errfmt);
                     67: }
                     68: 
                     69: XParse()
                     70: {
                     71:        char    *sstr;
                     72: 
                     73:        sstr = ask(errfmt, ProcFmt);
                     74:        ErrParse(sstr);
                     75: }
                     76: 
                     77: /* Parse for {C,LINT} errors (or anything that matches fmtstr) in the
                     78:    current buffer.  Set up for the next-error command.  This is neat
                     79:    because this will work for any kind of output that prints a file
                     80:    name and a line number on the same line. */
                     81: 
                     82: ErrParse(fmtstr)
                     83: char   *fmtstr;
                     84: {
                     85:        Bufpos  *bp;
                     86:        char    fname[FILESIZE],
                     87:                lineno[10],
                     88:                REbuf[128],
                     89:                *REalts[10];
                     90:        int     lnum,
                     91:                last_lnum = -1;
                     92:        struct error    *ep = 0;
                     93:        Buffer  *buf,
                     94:                *lastb = 0;
                     95:        Line    *err_line;      
                     96: 
                     97:        ErrFree();              /* This is important! */
                     98:        ToFirst();
                     99:        perr_buf = curbuf;
                    100:        REcompile(fmtstr, 1, REbuf, REalts);
                    101:        /* Find a line with a number on it. */
                    102:        while (bp = docompiled(FORWARD, REbuf, REalts)) {
                    103:                SetDot(bp);
                    104:                putmatch(1, fname, sizeof fname);
                    105:                putmatch(2, lineno, sizeof lineno);
                    106:                buf = do_find((Window *) 0, fname, 1);
                    107:                if (buf != lastb) {
                    108:                        lastb = buf;
                    109:                        last_lnum = -1;         /* signals new file */
                    110:                        err_line = buf->b_first;
                    111:                }
                    112:                lnum = chr_to_int(lineno, 10, 0);
                    113:                if (lnum == last_lnum)  /* one error per line is nicer */
                    114:                        continue;
                    115:                if (last_lnum == -1)
                    116:                        last_lnum = 1;  /* that's where we really are */
                    117:                err_line = next_line(err_line, lnum - last_lnum);
                    118:                ep = AddError(ep, curline, buf, err_line, 0);
                    119:                last_lnum = lnum;
                    120:        }
                    121:        if (cur_error != 0)
                    122:                ShowErr();
                    123:        exp = 1;
                    124: }
                    125: 
                    126: /* Free up all the errors */
                    127: 
                    128: ErrFree()
                    129: {
                    130:        register struct error   *ep;
                    131: 
                    132:        for (ep = errorlist; ep != 0; ep = ep->er_next)
                    133:                free((char *) ep);
                    134:        errorlist = cur_error = 0;
                    135: }
                    136: 
                    137: /* Internal next error sets cur_error to the next error, taking the
                    138:    argument count, supplied by the user, into consideration. */
                    139: 
                    140: private char   errbounds[] = "You're at the %s error.",
                    141:                noerrs[] = "No errors!";
                    142: 
                    143: private
                    144: toerror(forward)
                    145: {
                    146:        register int    i;
                    147:        register struct error   *e = cur_error;
                    148: 
                    149:        if (e == 0)
                    150:                complain(noerrs);
                    151:        if ((forward && (e->er_next == 0)) ||
                    152:            (!forward && (e->er_prev == 0)))
                    153:                complain(errbounds, forward ? "last" : "first");
                    154: 
                    155:        for (i = 0; i < exp; i++) {
                    156:                if ((e = forward ? e->er_next : e->er_prev) == 0)
                    157:                        break;
                    158:                cur_error = e;
                    159:        }
                    160: }
                    161: 
                    162: NextError()
                    163: {
                    164:        ToError(1);
                    165: }
                    166: 
                    167: PrevError()
                    168: {
                    169:        ToError(0);
                    170: }
                    171: 
                    172: private
                    173: okay_error()
                    174: {
                    175:        return ((inlist(perr_buf->b_first, cur_error->er_mess)) &&
                    176:                (inlist(cur_error->er_buf->b_first, cur_error->er_text)));
                    177: }
                    178: 
                    179: /* Go the the next error, if there is one.  Put the error buffer in
                    180:    one window and the buffer with the error in another window.
                    181:    It checks to make sure that the error actually exists. */
                    182: 
                    183: ToError(forward)
                    184: {
                    185:        do {
                    186:                toerror(forward);
                    187:                exp = 1;
                    188:        } while (!okay_error());
                    189:        ShowErr();
                    190: }
                    191: 
                    192: int    EWSize = 20;    /* percentage of screen the error window
                    193:                           should be */
                    194: 
                    195: /* Show the current error, i.e. put the line containing the error message
                    196:    in one window, and the buffer containing the actual error in another
                    197:    window. */
                    198: 
                    199: ShowErr()
                    200: {
                    201:        Window  *err_wind,
                    202:                *buf_wind;
                    203:        int     w_size;         /* size of window */
                    204: 
                    205:        if (cur_error == 0)
                    206:                complain(noerrs);
                    207:        if (!okay_error()) {
                    208:                rbell();
                    209:                return;
                    210:        }
                    211:        err_wind = windbp(perr_buf);
                    212:        buf_wind = windbp(cur_error->er_buf);
                    213: 
                    214:        if (err_wind && !buf_wind) {
                    215:                SetWind(err_wind);
                    216:                pop_wind(cur_error->er_buf->b_name, 0, -1);
                    217:                buf_wind = curwind;
                    218:        } else if (!err_wind && buf_wind) {
                    219:                SetWind(buf_wind);
                    220:                pop_wind(perr_buf->b_name, 0, -1);
                    221:                err_wind = curwind;
                    222:        } else if (!err_wind && !buf_wind) {
                    223:                pop_wind(perr_buf->b_name, 0, -1);
                    224:                err_wind = curwind;
                    225:                pop_wind(cur_error->er_buf->b_name, 0, -1);
                    226:                buf_wind = curwind;
                    227:        }
                    228: 
                    229:        /* Put the current error message at the top of its Window */
                    230:        SetWind(err_wind);
                    231:        SetLine(cur_error->er_mess);
                    232:        SetTop(curwind, (curwind->w_line = cur_error->er_mess));
                    233:        w_size = (ILI * EWSize) / 100;
                    234:        if (w_size >= 1)
                    235:                WindSize(curwind, w_size - (curwind->w_height - 1));
                    236: 
                    237:        /* now go to the the line with the error in the other window */
                    238:        SetWind(buf_wind);
                    239:        DotTo(cur_error->er_text, cur_error->er_char);
                    240: }
                    241: 
                    242: char   ShcomBuf[128] = {0};
                    243: 
                    244: /* Make a buffer name given the command `command', i.e. "fgrep -n foo *.c"
                    245:    will return the buffer name "fgrep".  */
                    246: 
                    247: char *
                    248: MakeName(command)
                    249: char   *command;
                    250: {
                    251:        static char     bufname[50];
                    252:        register char   *cp = bufname,
                    253:                        c;
                    254: 
                    255:        while ((c = *command++) && (c == ' ' || c == '\t'))
                    256:                ;
                    257:        do
                    258:                *cp++ = c;
                    259:        while ((c = *command++) && (c != ' ' && c != '\t'));
                    260:        *cp = 0;
                    261:        strcpy(bufname, basename(bufname));
                    262: 
                    263:        return bufname;
                    264: }
                    265: 
                    266: /* Run make, first writing all the modified buffers (if the WtOnMk flag is
                    267:    non-zero), parse the errors, and go the first error. */
                    268: 
                    269: char   make_cmd[128] = "make";
                    270: 
                    271: MakeErrors()
                    272: {
                    273:        Window  *old = curwind;
                    274:        int     status,
                    275:                compilation;
                    276:        
                    277:        if (WtOnMk)
                    278:                put_bufs(0);
                    279:        /* When we're not doing make or cc (i.e., the last command
                    280:           was probably a grep or something) and the user just types
                    281:           C-X C-E, he probably (possibly, hopefully, usually (in my
                    282:           case)) doesn't want to do the grep again but rather wants
                    283:           to do a make again; so we ring the bell and insert the
                    284:           default command and let the person decide. */
                    285: 
                    286:        compilation = (sindex("make", make_cmd) || sindex("cc", make_cmd));
                    287:        if (exp_p || !compilation) {
                    288:                if (!compilation) {
                    289:                        rbell();
                    290:                        Inputp = make_cmd;      /* insert the default for the
                    291:                                                   user */
                    292:                }
                    293:                null_ncpy(make_cmd, ask(make_cmd, "Compilation command: "),
                    294:                                sizeof (make_cmd) - 1);
                    295:        }
                    296:        status = UnixToBuf(MakeName(make_cmd), YES, EWSize, YES, Shell, basename(Shell), ShFlags, make_cmd, 0);
                    297:        com_finish(status, make_cmd);
                    298: 
                    299:        ErrParse(errfmt);
                    300: 
                    301:        if (!cur_error)
                    302:                SetWind(old);
                    303: }
                    304: 
                    305: #ifdef SPELL
                    306: 
                    307: SpelBuffer()
                    308: {
                    309:        char    *Spell = "Spell",
                    310:                com[100];
                    311:        Window  *savewp = curwind;
                    312: 
                    313:        put_bufs(0);
                    314:        sprintf(com, "spell %s", curbuf->b_fname);
                    315:        (void) UnixToBuf(Spell, YES, EWSize, YES, Shell, basename(Shell), ShFlags, com, 0);
                    316:        message("[Delete the irrelevant words and then type C-X C-C]");
                    317:        Recur();
                    318:        SetWind(savewp);
                    319:        SpelParse(Spell);
                    320: }
                    321: 
                    322: SpelWords()
                    323: {
                    324:        char    *buftospel;
                    325:        Buffer  *wordsb = curbuf;
                    326: 
                    327:        if ((buftospel = ask_buf((Buffer *) 0)) == 0)
                    328:                return;
                    329:        SetBuf(do_select(curwind, buftospel));
                    330:        SpelParse(wordsb->b_name);
                    331: }
                    332: 
                    333: SpelParse(bname)
                    334: char   *bname;
                    335: {
                    336:        Buffer  *buftospel,
                    337:                *wordsb;
                    338:        char    wordspel[100];
                    339:        Bufpos  *bp;
                    340:        struct error    *ep = 0;
                    341: 
                    342:        ErrFree();              /* This is important! */
                    343: 
                    344:        buftospel = curbuf;
                    345:        wordsb = buf_exists(bname);
                    346:        perr_buf = wordsb;      /* This is important (buffer containing
                    347:                                   error messages) */
                    348:        SetBuf(wordsb);
                    349:        ToFirst();
                    350:        f_mess("Finding misspelled words ... ");
                    351:        while (!lastp(curline)) {
                    352:                sprintf(wordspel, "\\<%s\\>", linebuf);
                    353:                SetBuf(buftospel);
                    354:                ToFirst();
                    355:                while (bp = dosearch(wordspel, 1, 1)) {
                    356:                        SetDot(bp);
                    357:                        ep = AddError(ep, wordsb->b_dot, buftospel,
                    358:                                          curline, curchar);
                    359:                }
                    360:                SetBuf(wordsb);
                    361:                line_move(FORWARD, NO);
                    362:        }
                    363:        add_mess("Done.");
                    364:        SetBuf(buftospel);
                    365:        ShowErr();
                    366: }
                    367: 
                    368: #endif SPELL
                    369: 
                    370: ShToBuf()
                    371: {
                    372:        char    bufname[100];
                    373: 
                    374:        strcpy(bufname, ask((char *) 0, "Buffer: "));
                    375:        DoShell(bufname, ask(ShcomBuf, "Command: "));
                    376: }
                    377: 
                    378: ShellCom()
                    379: {
                    380:        null_ncpy(ShcomBuf, ask(ShcomBuf, ProcFmt), (sizeof ShcomBuf) - 1);
                    381:        DoShell(MakeName(ShcomBuf), ShcomBuf);
                    382: }
                    383: 
                    384: /* Run the shell command into `bufname'.  Empty the buffer except when we
                    385:    give a numeric argument, in which case it inserts the output at the
                    386:    current position in the buffer.  */
                    387: 
                    388: private
                    389: DoShell(bufname, command)
                    390: char   *bufname,
                    391:        *command;
                    392: {
                    393:        Window  *savewp = curwind;
                    394:        int     status;
                    395: 
                    396:        exp = 1;
                    397:        status = UnixToBuf(bufname, YES, 0, !exp_p, Shell, basename(Shell),
                    398:                           ShFlags, command, 0);
                    399:        com_finish(status, command);
                    400:        SetWind(savewp);
                    401: }
                    402: 
                    403: private
                    404: com_finish(status, com)
                    405: char   *com;
                    406: {
                    407:        s_mess("\"%s\" completed %ssuccessfully.", com, status ? "un" : NullStr);
                    408: }
                    409: 
                    410: dowait(pid, status)
                    411: int    pid,
                    412:        *status;
                    413: {
                    414: #ifndef IPROCS
                    415: 
                    416:        int     rpid;
                    417: 
                    418:        while ((rpid = wait(status)) != pid)
                    419:                ;
                    420: #else
                    421: 
                    422: #ifdef BSD4_2
                    423: #   include <sys/wait.h>
                    424: #else
                    425: #   include <wait.h>
                    426: #endif
                    427: 
                    428:        union wait      w;
                    429:        int     rpid;
                    430: 
                    431:        for (;;) {
                    432: #ifndef VMUNIX
                    433:                rpid = wait2(&w.w_status, 0);
                    434: #else
                    435:                rpid = wait3(&w, 0, (struct rusage *) 0);
                    436: #endif
                    437:                if (rpid == pid) {
                    438:                        if (status)
                    439:                                *status = w.w_status;
                    440:                        break;
                    441:                } else
                    442:                        kill_off(rpid, w);
                    443:        }
                    444: #endif IPROCS
                    445: }
                    446: 
                    447: /* Run the command to bufname, erase the buffer if clobber is non-zero,
                    448:    and redisplay if disp is non-zero.  Leaves current buffer in `bufname'
                    449:    and leaves any windows it creates lying around.  It's up to the caller
                    450:    to fix everything up after we're done.  (Usually there's nothing to
                    451:    fix up.) */
                    452: 
                    453: /* VARARGS3 */
                    454: 
                    455: UnixToBuf(bufname, disp, wsize, clobber, cmd, args)
                    456: char   *bufname,
                    457:        *cmd;
                    458: {
                    459:        int     p[2],
                    460:                pid;
                    461:        extern int      ninbuf;
                    462:        Buffer  *bp;
                    463: 
                    464:        if (clobber && (bp = buf_exists(bufname)) != 0 &&
                    465:                        bp->b_type != B_PROCESS && bp->b_type != B_IPROCESS)
                    466:                complain("Command would over-write buffer %s.", bufname);
                    467:        if (disp) {
                    468:                message("Starting up...");
                    469:                pop_wind(bufname, clobber, clobber ? B_PROCESS : B_FILE);
                    470:                wsize = (LI * wsize) / 100;
                    471:                if (wsize >= 1 && !one_windp())
                    472:                        WindSize(curwind, wsize - (curwind->w_height - 1));
                    473:                redisplay();
                    474:        }
                    475:        exp = 1;
                    476:        dopipe(p);
                    477:        pid = fork();
                    478:        if (pid == -1) {
                    479:                pclose(p);
                    480:                complain("[Fork failed]");
                    481:        }
                    482:        if (pid == 0) {
                    483:                (void) close(0);
                    484:                (void) open("/dev/null", 0);
                    485:                (void) close(1);
                    486:                (void) close(2);
                    487:                (void) dup(p[1]);
                    488:                (void) dup(p[1]);
                    489:                pclose(p);
                    490:                execv(cmd, (char **) &args);
                    491:                (void) write(1, "Execl failed.\n", 14);
                    492:                _exit(1);
                    493:        } else {
                    494:                int     status;
                    495:                int     (*oldint)() = signal(SIGINT, SIG_IGN);
                    496:                char    *mess;
                    497:                File    *fp;
                    498: 
                    499: #ifdef IPROCS
                    500:                sighold(SIGCHLD);
                    501: #endif
                    502: 
                    503:                (void) close(p[1]);
                    504:                fp = fd_open(cmd, F_READ, p[0], iobuff, LBSIZE);
                    505:                while (inIOread = 1, f_gets(fp, genbuf, LBSIZE) != EOF) {
                    506:                        inIOread = 0;
                    507:                        ins_str(genbuf, YES);
                    508:                        LineInsert();
                    509:                        if (disp != 0 && fp->f_cnt <= 0) {
                    510: #ifdef LOAD_AV
                    511:                            {
                    512:                                double  theavg;
                    513: 
                    514:                                get_la(&theavg);
                    515:                                if (theavg < 2.0)
                    516:                                        mess = "Screaming along...";
                    517:                                else if (theavg < 5.0)
                    518:                                        mess = "Chugging along...";
                    519:                                else
                    520:                                        mess = "Crawling along...";
                    521:                            }
                    522: #else
                    523:                                mess = "Chugging along...";
                    524: #endif LOAD_AV
                    525:                                message(mess);
                    526:                                redisplay();
                    527:                        }
                    528:                }
                    529:                if (disp)
                    530:                        DrawMesg(NO);
                    531:                close_file(fp);
                    532:                (void) signal(SIGINT, oldint);
                    533:                dowait(pid, &status);
                    534: #ifdef IPROCS
                    535:                sigrelse(SIGCHLD);
                    536: #endif
                    537:                return status;
                    538:        }
                    539:        return 0;
                    540: }
                    541: 
                    542: #ifdef BSD4_2
                    543: 
                    544: private int    SigMask = 0;
                    545: 
                    546: sighold(sig)
                    547: {
                    548:        (void) sigblock(SigMask |= (1 << (sig - 1)));
                    549: }
                    550: 
                    551: sigrelse(sig)
                    552: {
                    553:        (void) sigsetmask(SigMask &= ~(1 << (sig - 1)));
                    554: }
                    555: 
                    556: #endif
                    557: 
                    558: FilterRegion()
                    559: {
                    560:        char    *cmd = ask((char *) 0, ": %f (through command) ", ProcFmt);
                    561: 
                    562:        RegToUnix(curbuf, cmd);
                    563: }
                    564: 
                    565: /* Send the current region to CMD and insert the output from the
                    566:    command into OUT_BUF. */
                    567: 
                    568: RegToUnix(outbuf, cmd)
                    569: Buffer *outbuf;
                    570: char   *cmd;
                    571: {
                    572:        Mark    *m = CurMark();
                    573:        char    *tname = mktemp("/tmp/jfilterXXXXXX"),
                    574:                combuf[130];
                    575:        Window  *save_wind = curwind;
                    576:        int     status;
                    577:        File    *fp;
                    578: 
                    579:     CATCH
                    580:        fp = open_file(tname, iobuff, F_WRITE, COMPLAIN, QUIET);
                    581:        putreg(fp, m->m_line, m->m_char, curline, curchar, YES);
                    582:        DelReg();
                    583:        sprintf(combuf, "%s < %s", cmd, tname);
                    584:        status = UnixToBuf(outbuf->b_name, NO, 0, outbuf->b_type == B_SCRATCH,
                    585:                           Shell, basename(Shell), ShFlags, combuf, 0);
                    586:     ONERROR
                    587:        ;       /* Do nothing ... but fall through and delete the tmp
                    588:                   file. */
                    589:     ENDCATCH
                    590:        f_close(fp);
                    591:        (void) unlink(tname);
                    592:        SetWind(save_wind);
                    593:        com_finish(status, combuf);
                    594: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.