Annotation of 43BSDReno/foreign/src/ex/ex_temp.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: static char *sccsid = "@(#)ex_temp.c   7.7.1.1 (Berkeley) 10/21/90";
                      9: #endif not lint
                     10: 
                     11: #include "ex.h"
                     12: #include "ex_temp.h"
                     13: #include "ex_vis.h"
                     14: #include "ex_tty.h"
                     15: #include "pathnames.h"
                     16: 
                     17: /*
                     18:  * Editor temporary file routines.
                     19:  * Very similar to those of ed, except uses 2 input buffers.
                     20:  */
                     21: #define        READ    0
                     22: #define        WRITE   1
                     23: 
                     24: #ifndef vms
                     25: #define        EPOSITION       7
                     26: #else
                     27: #define        EPOSITION       13
                     28: #endif
                     29: 
                     30: char   tfname[40];
                     31: char   rfname[40];
                     32: int    havetmp;
                     33: short  tfile = -1;
                     34: short  rfile = -1;
                     35: 
                     36: fileinit()
                     37: {
                     38:        register char *p;
                     39:        register int i, j;
                     40:        struct stat stbuf;
                     41: 
                     42:        if (tline == INCRMT * (HBLKS+2))
                     43:                return;
                     44:        cleanup(0);
                     45:        if (tfile >= 0)
                     46:                close(tfile);
                     47:        tline = INCRMT * (HBLKS+2);
                     48:        blocks[0] = HBLKS;
                     49:        blocks[1] = HBLKS+1;
                     50:        blocks[2] = -1;
                     51:        dirtcnt = 0;
                     52:        iblock = -1;
                     53:        iblock2 = -1;
                     54:        oblock = -1;
                     55:        CP(tfname, svalue(DIRECTORY));
                     56: #ifndef vms
                     57:        if (stat(tfname, &stbuf))
                     58: #else
                     59:        goto vms_no_check_dir;
                     60: #endif
                     61:        {
                     62: dumbness:
                     63:                if (setexit() == 0)
                     64:                        filioerr(tfname);
                     65:                else
                     66:                        putNFL();
                     67:                cleanup(1);
                     68:                ex_exit(1);
                     69:        }
                     70: #ifndef        vms
                     71:        if ((stbuf.st_mode & S_IFMT) != S_IFDIR) {
                     72:                errno = ENOTDIR;
                     73:                goto dumbness;
                     74:        }
                     75: #else
                     76: vms_no_check_dir:
                     77: #endif
                     78:        ichanged = 0;
                     79:        ichang2 = 0;
                     80: #ifndef        vms
                     81:        ignore(strcat(tfname, "/ExXXXXX"));
                     82: #else
                     83:        ignore(strcat(tfname, "ExXXXXX"));
                     84: #endif
                     85:        for (p = strend(tfname), i = 5, j = getpid(); i > 0; i--, j /= 10)
                     86:                *--p = j % 10 | '0';
                     87: #ifdef vms
                     88:        ignore(strcat(tfname, ".txt.1"));
                     89:        unlink(tfname);
                     90: #endif
                     91:        tfile = creat(tfname, 0600);
                     92:        if (tfile < 0)
                     93:                goto dumbness;
                     94: #ifdef VMUNIX
                     95:        {
                     96:                extern stilinc;         /* see below */
                     97:                stilinc = 0;
                     98:        }
                     99: #endif
                    100:        havetmp = 1;
                    101:        if (tfile >= 0)
                    102:                close(tfile);
                    103:        tfile = open(tfname, 2);
                    104:        if (tfile < 0)
                    105:                goto dumbness;
                    106: #ifdef UNIX_SBRK
                    107: /*     brk((char *)fendcore); */
                    108: #endif
                    109: }
                    110: 
                    111: cleanup(all)
                    112:        bool all;
                    113: {
                    114:        if (all) {
                    115:                putpad(TE);
                    116:                flush();
                    117:        }
                    118:        if (havetmp) {
                    119:                if (tfile >= 0)
                    120:                        close(tfile);
                    121:                unlink(tfname);
                    122:        }
                    123:        havetmp = 0;
                    124:        if (all && rfile >= 0) {
                    125:                if (rfile >= 0)
                    126:                        close(rfile);
                    127:                unlink(rfname);
                    128:                rfile = -1;
                    129:        }
                    130: }
                    131: 
                    132: getline(tl)
                    133:        line tl;
                    134: {
                    135:        register char *bp, *lp;
                    136:        register int nl;
                    137: 
                    138:        lp = linebuf;
                    139:        bp = getblock(tl, READ);
                    140:        nl = nleft;
                    141:        tl &= ~OFFMSK;
                    142:        while (*lp++ = *bp++)
                    143:                if (--nl == 0) {
                    144:                        bp = getblock(tl += INCRMT, READ);
                    145:                        nl = nleft;
                    146:                }
                    147: }
                    148: 
                    149: putline()
                    150: {
                    151:        register char *bp, *lp;
                    152:        register int nl;
                    153:        line tl;
                    154: 
                    155:        dirtcnt++;
                    156:        lp = linebuf;
                    157:        change();
                    158:        tl = tline;
                    159:        bp = getblock(tl, WRITE);
                    160:        nl = nleft;
                    161:        tl &= ~OFFMSK;
                    162:        while (*bp = *lp++) {
                    163:                if (*bp++ == '\n') {
                    164:                        *--bp = 0;
                    165:                        linebp = lp;
                    166:                        break;
                    167:                }
                    168:                if (--nl == 0) {
                    169:                        bp = getblock(tl += INCRMT, WRITE);
                    170:                        nl = nleft;
                    171:                }
                    172:        }
                    173:        tl = tline;
                    174:        tline += (((lp - linebuf) + BNDRY - 1) >> SHFT) & 077776;
                    175:        return (tl);
                    176: }
                    177: 
                    178: int    read();
                    179: int    write();
                    180: 
                    181: char *
                    182: getblock(atl, iof)
                    183:        line atl;
                    184:        int iof;
                    185: {
                    186:        register int bno, off;
                    187:        
                    188:        bno = (atl >> OFFBTS) & BLKMSK;
                    189:        off = (atl << SHFT) & LBTMSK;
                    190:        if (bno >= NMBLKS)
                    191:                error(" Tmp file too large");
                    192:        nleft = BUFSIZ - off;
                    193:        if (bno == iblock) {
                    194:                ichanged |= iof;
                    195:                hitin2 = 0;
                    196:                return (ibuff + off);
                    197:        }
                    198:        if (bno == iblock2) {
                    199:                ichang2 |= iof;
                    200:                hitin2 = 1;
                    201:                return (ibuff2 + off);
                    202:        }
                    203:        if (bno == oblock)
                    204:                return (obuff + off);
                    205:        if (iof == READ) {
                    206:                if (hitin2 == 0) {
                    207:                        if (ichang2) {
                    208:                                blkio(iblock2, ibuff2, write);
                    209:                        }
                    210:                        ichang2 = 0;
                    211:                        iblock2 = bno;
                    212:                        blkio(bno, ibuff2, read);
                    213:                        hitin2 = 1;
                    214:                        return (ibuff2 + off);
                    215:                }
                    216:                hitin2 = 0;
                    217:                if (ichanged) {
                    218:                        blkio(iblock, ibuff, write);
                    219:                }
                    220:                ichanged = 0;
                    221:                iblock = bno;
                    222:                blkio(bno, ibuff, read);
                    223:                return (ibuff + off);
                    224:        }
                    225:        if (oblock >= 0) {
                    226:                        blkio(oblock, obuff, write);
                    227:        }
                    228:        oblock = bno;
                    229:        return (obuff + off);
                    230: }
                    231: 
                    232: #ifdef VMUNIX
                    233: #ifdef vms
                    234: #define        INCORB  32
                    235: #else
                    236: #define        INCORB  64
                    237: #endif
                    238: char   incorb[INCORB+1][BUFSIZ];
                    239: #define        pagrnd(a)       ((char *)(((int)a)&~(BUFSIZ-1)))
                    240: int    stilinc;        /* up to here not written yet */
                    241: #endif
                    242: 
                    243: blkio(b, buf, iofcn)
                    244:        short b;
                    245:        char *buf;
                    246:        int (*iofcn)();
                    247: {
                    248: 
                    249: #ifdef VMUNIX
                    250:        if (b < INCORB) {
                    251:                if (iofcn == read) {
                    252:                        bcopy(pagrnd(incorb[b+1]), buf, BUFSIZ);
                    253:                        return;
                    254:                }
                    255:                bcopy(buf, pagrnd(incorb[b+1]), BUFSIZ);
                    256:                if (laste) {
                    257:                        if (b >= stilinc)
                    258:                                stilinc = b + 1;
                    259:                        return;
                    260:                }
                    261:        } else if (stilinc)
                    262:                tflush();
                    263: #endif
                    264:        lseek(tfile, (long) (unsigned) b * BUFSIZ, 0);
                    265:        if ((*iofcn)(tfile, buf, BUFSIZ) != BUFSIZ)
                    266:                filioerr(tfname);
                    267: }
                    268: 
                    269: #ifdef VMUNIX
                    270: tlaste()
                    271: {
                    272: 
                    273:        if (stilinc)
                    274:                dirtcnt = 0;
                    275: }
                    276: 
                    277: tflush()
                    278: {
                    279:        int i = stilinc;
                    280:        
                    281:        stilinc = 0;
                    282:        lseek(tfile, (long) 0, 0);
                    283:        if (write(tfile, pagrnd(incorb[1]), i * BUFSIZ) != (i * BUFSIZ))
                    284:                filioerr(tfname);
                    285: }
                    286: #endif
                    287: 
                    288: /*
                    289:  * Synchronize the state of the temporary file in case
                    290:  * a crash occurs.
                    291:  */
                    292: synctmp()
                    293: {
                    294:        register int cnt;
                    295:        register line *a;
                    296:        register short *bp;
                    297: 
                    298: #ifdef VMUNIX
                    299:        if (stilinc)
                    300:                return;
                    301: #endif
                    302:        if (dol == zero)
                    303:                return;
                    304:        if (ichanged)
                    305:                blkio(iblock, ibuff, write);
                    306:        ichanged = 0;
                    307:        if (ichang2)
                    308:                blkio(iblock2, ibuff2, write);
                    309:        ichang2 = 0;
                    310:        if (oblock != -1)
                    311:                blkio(oblock, obuff, write);
                    312:        time(&H.Time);
                    313:        uid = getuid();
                    314:        *zero = (line) H.Time;
                    315:        for (a = zero, bp = blocks; a <= dol; a += BUFSIZ / sizeof *a, bp++) {
                    316:                if (*bp < 0) {
                    317:                        tline = (tline + OFFMSK) &~ OFFMSK;
                    318:                        *bp = ((tline >> OFFBTS) & BLKMSK);
                    319:                        if (*bp > NMBLKS)
                    320:                                error(" Tmp file too large");
                    321:                        tline += INCRMT;
                    322:                        oblock = *bp + 1;
                    323:                        bp[1] = -1;
                    324:                }
                    325:                lseek(tfile, (long) (unsigned) *bp * BUFSIZ, 0);
                    326:                cnt = ((dol - a) + 2) * sizeof (line);
                    327:                if (cnt > BUFSIZ)
                    328:                        cnt = BUFSIZ;
                    329:                if (write(tfile, (char *) a, cnt) != cnt) {
                    330: oops:
                    331:                        *zero = 0;
                    332:                        filioerr(tfname);
                    333:                }
                    334:                *zero = 0;
                    335:        }
                    336:        flines = lineDOL();
                    337:        lseek(tfile, 0l, 0);
                    338:        if (write(tfile, (char *) &H, sizeof H) != sizeof H)
                    339:                goto oops;
                    340: #ifdef notdef
                    341:        /*
                    342:         * This will insure that exrecover gets as much
                    343:         * back after a crash as is absolutely possible,
                    344:         * but can result in pregnant pauses between commands
                    345:         * when the TSYNC call is made, so...
                    346:         */
                    347: #ifndef vms
                    348:        (void) fsync(tfile);
                    349: #endif
                    350: #endif
                    351: }
                    352: 
                    353: TSYNC()
                    354: {
                    355: 
                    356:        if (dirtcnt > MAXDIRT) {        /* mjm: 12 --> MAXDIRT */
                    357: #ifdef VMUNIX
                    358:                if (stilinc)
                    359:                        tflush();
                    360: #endif
                    361:                dirtcnt = 0;
                    362:                synctmp();
                    363:        }
                    364: }
                    365: 
                    366: /*
                    367:  * Named buffer routines.
                    368:  * These are implemented differently than the main buffer.
                    369:  * Each named buffer has a chain of blocks in the register file.
                    370:  * Each block contains roughly 508 chars of text,
                    371:  * and a previous and next block number.  We also have information
                    372:  * about which blocks came from deletes of multiple partial lines,
                    373:  * e.g. deleting a sentence or a LISP object.
                    374:  *
                    375:  * We maintain a free map for the temp file.  To free the blocks
                    376:  * in a register we must read the blocks to find how they are chained
                    377:  * together.
                    378:  *
                    379:  * BUG:                The default savind of deleted lines in numbered
                    380:  *             buffers may be rather inefficient; it hasn't been profiled.
                    381:  */
                    382: struct strreg {
                    383:        short   rg_flags;
                    384:        short   rg_nleft;
                    385:        short   rg_first;
                    386:        short   rg_last;
                    387: } strregs[('z'-'a'+1) + ('9'-'0'+1)], *strp;
                    388: 
                    389: struct rbuf {
                    390:        short   rb_prev;
                    391:        short   rb_next;
                    392:        char    rb_text[BUFSIZ - 2 * sizeof (short)];
                    393: } *rbuf, KILLrbuf, putrbuf, YANKrbuf, regrbuf;
                    394: #ifdef VMUNIX
                    395: short  rused[256];
                    396: #else
                    397: short  rused[32];
                    398: #endif
                    399: short  rnleft;
                    400: short  rblock;
                    401: short  rnext;
                    402: char   *rbufcp;
                    403: 
                    404: regio(b, iofcn)
                    405:        short b;
                    406:        int (*iofcn)();
                    407: {
                    408: 
                    409:        if (rfile == -1) {
                    410:                CP(rfname, tfname);
                    411:                *(strend(rfname) - EPOSITION) = 'R';
                    412:                rfile = creat(rfname, 0600);
                    413:                if (rfile < 0)
                    414: oops:
                    415:                        filioerr(rfname);
                    416:                else
                    417:                        close(rfile);
                    418:                rfile = open(rfname, 2);
                    419:                if (rfile < 0)
                    420:                        goto oops;
                    421:        }
                    422:        lseek(rfile, (long) b * BUFSIZ, 0);
                    423:        if ((*iofcn)(rfile, rbuf, BUFSIZ) != BUFSIZ)
                    424:                goto oops;
                    425:        rblock = b;
                    426: }
                    427: 
                    428: REGblk()
                    429: {
                    430:        register int i, j, m;
                    431: 
                    432:        for (i = 0; i < sizeof rused / sizeof rused[0]; i++) {
                    433:                m = (rused[i] ^ 0177777) & 0177777;
                    434:                if (i == 0)
                    435:                        m &= ~1;
                    436:                if (m != 0) {
                    437:                        j = 0;
                    438:                        while ((m & 1) == 0)
                    439:                                j++, m >>= 1;
                    440:                        rused[i] |= (1 << j);
                    441: #ifdef RDEBUG
                    442:                        ex_printf("allocating block %d\n", i * 16 + j);
                    443: #endif
                    444:                        return (i * 16 + j);
                    445:                }
                    446:        }
                    447:        error("Out of register space (ugh)");
                    448:        /*NOTREACHED*/
                    449: }
                    450: 
                    451: struct strreg *
                    452: mapreg(c)
                    453:        register int c;
                    454: {
                    455: 
                    456:        if (isupper(c))
                    457:                c = tolower(c);
                    458:        return (isdigit(c) ? &strregs[('z'-'a'+1)+(c-'0')] : &strregs[c-'a']);
                    459: }
                    460: 
                    461: int    shread();
                    462: 
                    463: KILLreg(c)
                    464:        register int c;
                    465: {
                    466:        register struct strreg *sp;
                    467: 
                    468:        rbuf = &KILLrbuf;
                    469:        sp = mapreg(c);
                    470:        rblock = sp->rg_first;
                    471:        sp->rg_first = sp->rg_last = 0;
                    472:        sp->rg_flags = sp->rg_nleft = 0;
                    473:        while (rblock != 0) {
                    474: #ifdef RDEBUG
                    475:                ex_printf("freeing block %d\n", rblock);
                    476: #endif
                    477:                rused[rblock / 16] &= ~(1 << (rblock % 16));
                    478:                regio(rblock, shread);
                    479:                rblock = rbuf->rb_next;
                    480:        }
                    481: }
                    482: 
                    483: /*VARARGS*/
                    484: shread()
                    485: {
                    486:        struct front { short a; short b; };
                    487: 
                    488:        if (read(rfile, (char *) rbuf, sizeof (struct front)) == sizeof (struct front))
                    489:                return (sizeof (struct rbuf));
                    490:        return (0);
                    491: }
                    492: 
                    493: int    getREG();
                    494: 
                    495: putreg(c)
                    496:        char c;
                    497: {
                    498:        register line *odot = dot;
                    499:        register line *odol = dol;
                    500:        register int cnt;
                    501: 
                    502:        deletenone();
                    503:        appendnone();
                    504:        rbuf = &putrbuf;
                    505:        rnleft = 0;
                    506:        rblock = 0;
                    507:        rnext = mapreg(c)->rg_first;
                    508:        if (rnext == 0) {
                    509:                if (inopen) {
                    510:                        splitw++;
                    511:                        vclean();
                    512:                        vgoto(WECHO, 0);
                    513:                }
                    514:                vreg = -1;
                    515:                error("Nothing in register %c", c);
                    516:        }
                    517:        if (inopen && partreg(c)) {
                    518:                if (!FIXUNDO) {
                    519:                        splitw++; vclean(); vgoto(WECHO, 0); vreg = -1;
                    520:                        error("Can't put partial line inside macro");
                    521:                }
                    522:                squish();
                    523:                addr1 = addr2 = dol;
                    524:        }
                    525:        cnt = append(getREG, addr2);
                    526:        if (inopen && partreg(c)) {
                    527:                unddol = dol;
                    528:                dol = odol;
                    529:                dot = odot;
                    530:                pragged(0);
                    531:        }
                    532:        killcnt(cnt);
                    533:        notecnt = cnt;
                    534: }
                    535: 
                    536: partreg(c)
                    537:        char c;
                    538: {
                    539: 
                    540:        return (mapreg(c)->rg_flags);
                    541: }
                    542: 
                    543: notpart(c)
                    544:        register int c;
                    545: {
                    546: 
                    547:        if (c)
                    548:                mapreg(c)->rg_flags = 0;
                    549: }
                    550: 
                    551: getREG()
                    552: {
                    553:        register char *lp = linebuf;
                    554:        register int c;
                    555: 
                    556:        for (;;) {
                    557:                if (rnleft == 0) {
                    558:                        if (rnext == 0)
                    559:                                return (EOF);
                    560:                        regio(rnext, read);
                    561:                        rnext = rbuf->rb_next;
                    562:                        rbufcp = rbuf->rb_text;
                    563:                        rnleft = sizeof rbuf->rb_text;
                    564:                }
                    565:                c = *rbufcp;
                    566:                if (c == 0)
                    567:                        return (EOF);
                    568:                rbufcp++, --rnleft;
                    569:                if (c == '\n') {
                    570:                        *lp++ = 0;
                    571:                        return (0);
                    572:                }
                    573:                *lp++ = c;
                    574:        }
                    575: }
                    576: 
                    577: YANKreg(c)
                    578:        register int c;
                    579: {
                    580:        register line *addr;
                    581:        register struct strreg *sp;
                    582:        char savelb[LBSIZE];
                    583: 
                    584:        if (isdigit(c))
                    585:                kshift();
                    586:        if (islower(c))
                    587:                KILLreg(c);
                    588:        strp = sp = mapreg(c);
                    589:        sp->rg_flags = inopen && cursor && wcursor;
                    590:        rbuf = &YANKrbuf;
                    591:        if (sp->rg_last) {
                    592:                regio(sp->rg_last, read);
                    593:                rnleft = sp->rg_nleft;
                    594:                rbufcp = &rbuf->rb_text[sizeof rbuf->rb_text - rnleft];
                    595:        } else {
                    596:                rblock = 0;
                    597:                rnleft = 0;
                    598:        }
                    599:        CP(savelb,linebuf);
                    600:        for (addr = addr1; addr <= addr2; addr++) {
                    601:                getline(*addr);
                    602:                if (sp->rg_flags) {
                    603:                        if (addr == addr2)
                    604:                                *wcursor = 0;
                    605:                        if (addr == addr1)
                    606:                                strcpy(linebuf, cursor);
                    607:                }
                    608:                YANKline();
                    609:        }
                    610:        rbflush();
                    611:        killed();
                    612:        CP(linebuf,savelb);
                    613: }
                    614: 
                    615: kshift()
                    616: {
                    617:        register int i;
                    618: 
                    619:        KILLreg('9');
                    620:        for (i = '8'; i >= '0'; i--)
                    621:                copy(mapreg(i+1), mapreg(i), sizeof (struct strreg));
                    622: }
                    623: 
                    624: YANKline()
                    625: {
                    626:        register char *lp = linebuf;
                    627:        register struct rbuf *rp = rbuf;
                    628:        register int c;
                    629: 
                    630:        do {
                    631:                c = *lp++;
                    632:                if (c == 0)
                    633:                        c = '\n';
                    634:                if (rnleft == 0) {
                    635:                        rp->rb_next = REGblk();
                    636:                        rbflush();
                    637:                        rblock = rp->rb_next;
                    638:                        rp->rb_next = 0;
                    639:                        rp->rb_prev = rblock;
                    640:                        rnleft = sizeof rp->rb_text;
                    641:                        rbufcp = rp->rb_text;
                    642:                }
                    643:                *rbufcp++ = c;
                    644:                --rnleft;
                    645:        } while (c != '\n');
                    646:        if (rnleft)
                    647:                *rbufcp = 0;
                    648: }
                    649: 
                    650: rbflush()
                    651: {
                    652:        register struct strreg *sp = strp;
                    653: 
                    654:        if (rblock == 0)
                    655:                return;
                    656:        regio(rblock, write);
                    657:        if (sp->rg_first == 0)
                    658:                sp->rg_first = rblock;
                    659:        sp->rg_last = rblock;
                    660:        sp->rg_nleft = rnleft;
                    661: }
                    662: 
                    663: /* Register c to char buffer buf of size buflen */
                    664: regbuf(c, buf, buflen)
                    665: char c;
                    666: char *buf;
                    667: int buflen;
                    668: {
                    669:        register char *p, *lp;
                    670: 
                    671:        rbuf = &regrbuf;
                    672:        rnleft = 0;
                    673:        rblock = 0;
                    674:        rnext = mapreg(c)->rg_first;
                    675:        if (rnext==0) {
                    676:                *buf = 0;
                    677:                error("Nothing in register %c",c);
                    678:        }
                    679:        p = buf;
                    680:        while (getREG()==0) {
                    681:                for (lp=linebuf; *lp;) {
                    682:                        if (p >= &buf[buflen])
                    683:                                error("Register too long@to fit in memory");
                    684:                        *p++ = *lp++;
                    685:                }
                    686:                *p++ = '\n';
                    687:        }
                    688:        if (partreg(c)) p--;
                    689:        *p = '\0';
                    690:        getDOT();
                    691: }
                    692: 
                    693: /*
                    694:  * Encryption routines.  These are essentially unmodified from ed.
                    695:  */
                    696: 

unix.superglobalmegacorp.com

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