Annotation of 43BSD/contrib/jove/proc.c, revision 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.